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.
3994 lines
88 KiB
3994 lines
88 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
requestm.c
|
|
|
|
Abstract:
|
|
|
|
NDIS miniport request routines.
|
|
|
|
Author:
|
|
|
|
Sean Selitrennikoff (SeanSe) 05-Oct-93
|
|
Jameel Hyder (JameelH) Re-organization 01-Jun-95
|
|
|
|
Environment:
|
|
|
|
Kernel mode, FSD
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Define the module number for debug code.
|
|
//
|
|
#define MODULE_NUMBER MODULE_REQUESTM
|
|
|
|
//
|
|
// This macro verifies the query information buffer length.
|
|
//
|
|
#define VERIFY_QUERY_PARAMETERS(_Request, _SizeNeeded, _Status) \
|
|
{ \
|
|
if ((_Request)->DATA.QUERY_INFORMATION.InformationBufferLength < (_SizeNeeded)) \
|
|
{ \
|
|
(_Request)->DATA.QUERY_INFORMATION.BytesNeeded = (_SizeNeeded); \
|
|
\
|
|
Status = NDIS_STATUS_INVALID_LENGTH; \
|
|
} \
|
|
else \
|
|
{ \
|
|
Status = NDIS_STATUS_SUCCESS; \
|
|
} \
|
|
}
|
|
|
|
//
|
|
// This macro verifies the set information buffer length.
|
|
//
|
|
#define VERIFY_SET_PARAMETERS(_Request, _SizeNeeded, _Status) \
|
|
{ \
|
|
if ((_Request)->DATA.SET_INFORMATION.InformationBufferLength < (_SizeNeeded)) \
|
|
{ \
|
|
(_Request)->DATA.SET_INFORMATION.BytesNeeded = (_SizeNeeded); \
|
|
\
|
|
Status = NDIS_STATUS_INVALID_LENGTH; \
|
|
} \
|
|
else \
|
|
{ \
|
|
Status = NDIS_STATUS_SUCCESS; \
|
|
} \
|
|
}
|
|
|
|
VOID
|
|
ndisMQueueRequest(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request,
|
|
IN PNDIS_M_OPEN_BLOCK Open
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_REQUEST *ppReq;
|
|
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Next = NULL;
|
|
if (Open != NULL)
|
|
{
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open = Open;
|
|
Open->References++;
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("+ Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
}
|
|
|
|
for (ppReq = &Miniport->PendingRequest;
|
|
*ppReq != NULL;
|
|
NOTHING)
|
|
{
|
|
ppReq = &(PNDIS_RESERVED_FROM_PNDIS_REQUEST(*ppReq))->Next;
|
|
}
|
|
*ppReq = Request;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMAllocateRequest(
|
|
OUT PNDIS_REQUEST * pRequest,
|
|
IN NDIS_REQUEST_TYPE RequestType,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will allocate a request to be used as an internal request.
|
|
|
|
Arguments:
|
|
|
|
Request - Will contain a pointer to the new request on exit.
|
|
RequestType - Type of ndis request.
|
|
Oid - Request identifier.
|
|
Buffer - Pointer to the buffer for the request.
|
|
BufferLength- Length of the buffer.
|
|
Context1 - This is the type of request.
|
|
Context2 - Information that will be needed when the internal request
|
|
completes.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if the request allocation succeeded.
|
|
NDIS_STATUS_FAILURE otherwise.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_REQUEST Request;
|
|
ULONG SizeNeeded;
|
|
PVOID Data;
|
|
|
|
//
|
|
// Allocate the request structure.
|
|
//
|
|
SizeNeeded = sizeof(NDIS_REQUEST) + BufferLength;
|
|
Data = ALLOC_FROM_POOL(SizeNeeded, NDIS_TAG_Q_REQ);
|
|
if (NULL == Data)
|
|
{
|
|
*pRequest = NULL;
|
|
return(NDIS_STATUS_RESOURCES);
|
|
}
|
|
|
|
//
|
|
// Zero out the request.
|
|
//
|
|
ZeroMemory(Data, SizeNeeded);
|
|
|
|
//
|
|
// Get a pointer to the request.
|
|
//
|
|
Request = Data;
|
|
|
|
//
|
|
// Set the request type.
|
|
//
|
|
Request->RequestType = RequestType;
|
|
|
|
//
|
|
// Copy the buffer that was passed to us into
|
|
// the new buffer.
|
|
//
|
|
if ((BufferLength > 0) &&
|
|
(Buffer != NULL) &&
|
|
(RequestType != NdisRequestQueryInformation) &&
|
|
(RequestType != NdisRequestQueryStatistics))
|
|
{
|
|
MoveMemory(Request + 1, Buffer, BufferLength);
|
|
}
|
|
|
|
//
|
|
// Initialize depending upon request type.
|
|
//
|
|
switch (RequestType)
|
|
{
|
|
case NdisRequestQueryStatistics:
|
|
case NdisRequestQueryInformation:
|
|
Request->DATA.QUERY_INFORMATION.Oid = Oid;
|
|
if ((BufferLength > 0) && (Buffer != NULL))
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = Request + 1;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
|
|
}
|
|
|
|
break;
|
|
|
|
case NdisRequestSetInformation:
|
|
Request->DATA.SET_INFORMATION.Oid = Oid;
|
|
if ((BufferLength > 0) && (Buffer != NULL))
|
|
{
|
|
Request->DATA.SET_INFORMATION.InformationBuffer = Request + 1;
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Give it back to the caller.
|
|
//
|
|
*pRequest = Request;
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMRestoreFilterSettings(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_M_OPEN_BLOCK Open
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will build request's to send down to the driver to
|
|
restore the filter settings. we have free run of the request queue
|
|
since we just reset it.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_REQUEST Request;
|
|
NDIS_STATUS Status;
|
|
ULONG PacketFilter;
|
|
UINT NumberOfAddresses;
|
|
UINT FunctionalAddress;
|
|
UINT GroupAddress;
|
|
PSINGLE_LIST_ENTRY Link;
|
|
|
|
//
|
|
// Get the packet filter for the media type.
|
|
//
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMedium802_3:
|
|
PacketFilter = ETH_QUERY_FILTER_CLASSES(Miniport->EthDB);
|
|
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
PacketFilter = TR_QUERY_FILTER_CLASSES(Miniport->TrDB);
|
|
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
PacketFilter = FDDI_QUERY_FILTER_CLASSES(Miniport->FddiDB);
|
|
|
|
break;
|
|
|
|
case NdisMediumArcnet878_2:
|
|
PacketFilter = ARC_QUERY_FILTER_CLASSES(Miniport->ArcDB);
|
|
PacketFilter |= ETH_QUERY_FILTER_CLASSES(Miniport->EthDB);
|
|
|
|
if (MINIPORT_TEST_FLAG(
|
|
Miniport,
|
|
fMINIPORT_ARCNET_BROADCAST_SET) ||
|
|
(PacketFilter & NDIS_PACKET_TYPE_MULTICAST))
|
|
{
|
|
PacketFilter &= ~NDIS_PACKET_TYPE_MULTICAST;
|
|
PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Allocate a request to restore the packet filter.
|
|
//
|
|
Status = ndisMAllocateRequest(&Request,
|
|
NdisRequestSetInformation,
|
|
OID_GEN_CURRENT_PACKET_FILTER,
|
|
&PacketFilter,
|
|
sizeof(PacketFilter));
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Should do something here!!
|
|
//
|
|
}
|
|
|
|
ndisMQueueRequest(Miniport, Request, Open);
|
|
|
|
//
|
|
// Now build media dependant requests.
|
|
//
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMedium802_3:
|
|
|
|
///
|
|
// For ethernet we need to restore the multicast address list.
|
|
///
|
|
|
|
//
|
|
// Get a list of all the multicast address that need
|
|
// to be set.
|
|
//
|
|
EthQueryGlobalFilterAddresses(&Status,
|
|
Miniport->EthDB,
|
|
NDIS_M_MAX_MULTI_LIST * ETH_LENGTH_OF_ADDRESS,
|
|
&NumberOfAddresses,
|
|
(PVOID)Miniport->MulticastBuffer);
|
|
|
|
//
|
|
// Allocate a request to restore the multicast address list.
|
|
//
|
|
Status = ndisMAllocateRequest(&Request,
|
|
NdisRequestSetInformation,
|
|
OID_802_3_MULTICAST_LIST,
|
|
Miniport->MulticastBuffer,
|
|
NumberOfAddresses * ETH_LENGTH_OF_ADDRESS);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Should do something here!!
|
|
//
|
|
}
|
|
|
|
ndisMQueueRequest(Miniport, Request, Open);
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
|
|
///
|
|
// For token ring we need to restore the functional address
|
|
// and the group address.
|
|
///
|
|
|
|
//
|
|
// Get the current functional address from the filter
|
|
// library.
|
|
//
|
|
FunctionalAddress = TR_QUERY_FILTER_ADDRESSES(Miniport->TrDB);
|
|
FunctionalAddress = BYTE_SWAP_ULONG(FunctionalAddress);
|
|
|
|
//
|
|
// Allocate a request to restore the functional address.
|
|
//
|
|
Status = ndisMAllocateRequest(&Request,
|
|
NdisRequestSetInformation,
|
|
OID_802_5_CURRENT_FUNCTIONAL,
|
|
&FunctionalAddress,
|
|
sizeof(FunctionalAddress));
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Should do something here!!
|
|
//
|
|
}
|
|
|
|
ndisMQueueRequest(Miniport, Request, Open);
|
|
|
|
//
|
|
// Get the current group address from the filter library.
|
|
//
|
|
GroupAddress = TR_QUERY_FILTER_GROUP(Miniport->TrDB);
|
|
GroupAddress = BYTE_SWAP_ULONG(GroupAddress);
|
|
|
|
//
|
|
// Allocate a request to restore the group address.
|
|
//
|
|
Status = ndisMAllocateRequest(&Request,
|
|
NdisRequestSetInformation,
|
|
OID_802_5_CURRENT_GROUP,
|
|
&GroupAddress,
|
|
sizeof(GroupAddress));
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Should do something here!!
|
|
//
|
|
}
|
|
|
|
ndisMQueueRequest(Miniport, Request, Open);
|
|
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
|
|
///
|
|
// For FDDI we need to restore the long multicast address
|
|
// list and the short multicast address list.
|
|
///
|
|
|
|
//
|
|
// Get the number of multicast addresses and the list
|
|
// of multicast addresses to send to the miniport driver.
|
|
//
|
|
FddiQueryGlobalFilterLongAddresses(&Status,
|
|
Miniport->FddiDB,
|
|
NDIS_M_MAX_MULTI_LIST * FDDI_LENGTH_OF_LONG_ADDRESS,
|
|
&NumberOfAddresses,
|
|
(PVOID)Miniport->MulticastBuffer);
|
|
|
|
//
|
|
// Allocate a request to restore the long multicast address list.
|
|
//
|
|
Status = ndisMAllocateRequest(&Request,
|
|
NdisRequestSetInformation,
|
|
OID_FDDI_LONG_MULTICAST_LIST,
|
|
Miniport->MulticastBuffer,
|
|
NumberOfAddresses * FDDI_LENGTH_OF_LONG_ADDRESS);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Should do something here!!
|
|
//
|
|
}
|
|
|
|
ndisMQueueRequest(Miniport, Request, Open);
|
|
|
|
//
|
|
// Get the number of multicast addresses and the list
|
|
// of multicast addresses to send to the miniport driver.
|
|
//
|
|
FddiQueryGlobalFilterShortAddresses(&Status,
|
|
Miniport->FddiDB,
|
|
NDIS_M_MAX_MULTI_LIST * FDDI_LENGTH_OF_SHORT_ADDRESS,
|
|
&NumberOfAddresses,
|
|
(PVOID)Miniport->MulticastBuffer);
|
|
|
|
//
|
|
// Allocate a request to restore the short multicast address list.
|
|
//
|
|
Status = ndisMAllocateRequest(&Request,
|
|
NdisRequestSetInformation,
|
|
OID_FDDI_SHORT_MULTICAST_LIST,
|
|
Miniport->MulticastBuffer,
|
|
NumberOfAddresses * FDDI_LENGTH_OF_SHORT_ADDRESS);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Should do something here!!
|
|
//
|
|
}
|
|
|
|
ndisMQueueRequest(Miniport, Request, Open);
|
|
|
|
break;
|
|
|
|
case NdisMediumArcnet878_2:
|
|
|
|
//
|
|
// Only the packet filter is restored for arcnet and
|
|
// that was done above.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL, NULL);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisMRequest(
|
|
IN NDIS_HANDLE NdisBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_M_OPEN_BLOCK Open = (PNDIS_M_OPEN_BLOCK)NdisBindingHandle;
|
|
PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
|
|
PNDIS_REQUEST_RESERVED Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(NdisRequest);
|
|
BOOLEAN LocalLock;
|
|
KIRQL OldIrql;
|
|
NDIS_STATUS Status;
|
|
PSINGLE_LIST_ENTRY Link;
|
|
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
|
|
|
|
//
|
|
// Get protocol-options
|
|
//
|
|
if ((NdisRequest->RequestType == NdisRequestSetInformation) &&
|
|
(NdisRequest->DATA.SET_INFORMATION.Oid == OID_GEN_PROTOCOL_OPTIONS) &&
|
|
(NdisRequest->DATA.SET_INFORMATION.InformationBuffer != NULL))
|
|
{
|
|
PULONG ProtocolOptions;
|
|
|
|
ProtocolOptions = (PULONG)(NdisRequest->DATA.SET_INFORMATION.InformationBuffer);
|
|
if (*ProtocolOptions & NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT)
|
|
{
|
|
*ProtocolOptions &= ~NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT;
|
|
Open->Flags |= fMINIPORT_OPEN_NO_PROT_RSVD;
|
|
Open->FakeOpen->NoProtRsvdOnRcvPkt = TRUE;
|
|
}
|
|
if ((*ProtocolOptions & NDIS_PROT_OPTION_NO_LOOPBACK) &&
|
|
(Miniport->MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK))
|
|
{
|
|
*ProtocolOptions &= ~fMINIPORT_OPEN_NO_LOOPBACK;
|
|
Open->Flags |= NDIS_PROT_OPTION_NO_LOOPBACK;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Is there a reset in progress?
|
|
//
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS))
|
|
{
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
|
|
|
return(NDIS_STATUS_RESET_IN_PROGRESS);
|
|
}
|
|
|
|
LOCK_MINIPORT(Miniport, LocalLock);
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Got request 0x%x\n", NdisRequest));
|
|
|
|
//
|
|
// Place the new request on the pending queue.
|
|
//
|
|
ndisMQueueRequest(
|
|
Miniport,
|
|
NdisRequest,
|
|
(PNDIS_M_OPEN_BLOCK)NdisBindingHandle);
|
|
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL, NULL);
|
|
|
|
if (LocalLock)
|
|
{
|
|
//
|
|
// If we did not lock down the mini-port, then some other routine will
|
|
// do this processing for us. Otherwise we need to do this processing.
|
|
//
|
|
NDISM_PROCESS_DEFERRED(Miniport);
|
|
}
|
|
|
|
UNLOCK_MINIPORT(Miniport, LocalLock);
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMUndoBogusFilters(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes the bogus filter packages created in NdisCallDriverAddAdapter.
|
|
|
|
Arguments:
|
|
|
|
Miniport - Pointer to the Miniport.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
EthDeleteFilter(Miniport->EthDB);
|
|
Miniport->EthDB = NULL;
|
|
TrDeleteFilter(Miniport->TrDB);
|
|
Miniport->TrDB = NULL;
|
|
FddiDeleteFilter(Miniport->FddiDB);
|
|
Miniport->FddiDB = NULL;
|
|
ArcDeleteFilter(Miniport->ArcDB);
|
|
Miniport->ArcDB = NULL;
|
|
}
|
|
|
|
LONG
|
|
ndisMDoMiniportOp(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN BOOLEAN Query,
|
|
IN ULONG Oid,
|
|
IN PVOID Buf,
|
|
IN LONG BufSize,
|
|
IN LONG ErrorCodesToReturn
|
|
)
|
|
|
|
{
|
|
KIRQL OldIrql;
|
|
NTSTATUS NtStatus;
|
|
NDIS_STATUS NdisStatus;
|
|
LONG ErrorCode = 0;
|
|
UINT BytesWritten;
|
|
UINT BytesNeeded;
|
|
BOOLEAN LocalLock;
|
|
PNDIS_MINIPORT_WORK_ITEM WorkItem;
|
|
|
|
RAISE_IRQL_TO_DISPATCH(&OldIrql);
|
|
BLOCK_LOCK_MINIPORT_DPC(Miniport, LocalLock);
|
|
|
|
//
|
|
// Save a pointer to the miniport block as the
|
|
// current request. This will tell us that this request
|
|
// needs to be completed by setting the event.
|
|
//
|
|
Miniport->MiniportRequest = (PNDIS_REQUEST)Miniport;
|
|
|
|
//
|
|
// Do the appropriate operation.
|
|
//
|
|
if (Query)
|
|
{
|
|
NdisStatus = (Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Oid,
|
|
Buf,
|
|
BufSize,
|
|
&BytesWritten,
|
|
&BytesNeeded);
|
|
}
|
|
else
|
|
{
|
|
NdisStatus = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Oid,
|
|
Buf,
|
|
BufSize,
|
|
&BytesWritten,
|
|
&BytesNeeded);
|
|
}
|
|
|
|
|
|
//
|
|
// Fire a DPC to do anything
|
|
//
|
|
if ((NdisStatus == NDIS_STATUS_PENDING) ||
|
|
(NdisStatus == NDIS_STATUS_SUCCESS))
|
|
{
|
|
//
|
|
// Queue a dpc to fire.
|
|
//
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemDpc, &Miniport->Dpc, NULL);
|
|
NDISM_PROCESS_DEFERRED(Miniport);
|
|
}
|
|
|
|
UNLOCK_MINIPORT(Miniport, LocalLock);
|
|
LOWER_IRQL(OldIrql);
|
|
|
|
if (NdisStatus == NDIS_STATUS_PENDING)
|
|
{
|
|
LARGE_INTEGER TimeoutValue;
|
|
|
|
TimeoutValue.QuadPart = Int32x32To64(1000, -10000); // Make it 1 second
|
|
|
|
//
|
|
// The completion routine will set NdisRequestStatus.
|
|
//
|
|
NtStatus = WAIT_FOR_OBJECT(&Miniport->RequestEvent, &TimeoutValue);
|
|
|
|
NdisStatus = Miniport->RequestStatus;
|
|
|
|
if ((NtStatus != STATUS_SUCCESS) ||
|
|
(NdisStatus != NDIS_STATUS_SUCCESS))
|
|
{
|
|
//
|
|
// Halt the miniport driver
|
|
//
|
|
BLOCK_LOCK_MINIPORT(Miniport, LocalLock);
|
|
|
|
(Miniport->DriverHandle->MiniportCharacteristics.HaltHandler)(Miniport->MiniportAdapterContext);
|
|
|
|
UNLOCK_MINIPORT(Miniport, LocalLock);
|
|
|
|
ErrorCode = (NtStatus != STATUS_SUCCESS) ? ErrorCodesToReturn : ErrorCodesToReturn + 1;
|
|
}
|
|
|
|
RESET_EVENT(&Miniport->RequestEvent);
|
|
}
|
|
|
|
return(ErrorCode);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMFilterOutStatisticsOids(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will filter out any statistics OIDs.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
ULONG c;
|
|
PNDIS_OID OidList;
|
|
ULONG TotalOids;
|
|
ULONG CurrentDestOid;
|
|
|
|
//
|
|
// Initialize some temp variables.
|
|
//
|
|
OidList = Request->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
TotalOids = Request->DATA.QUERY_INFORMATION.BytesWritten / sizeof(NDIS_OID);
|
|
|
|
//
|
|
// Copy the information OIDs to the buffer that
|
|
// was passed with the original request.
|
|
//
|
|
for (c = 0, CurrentDestOid = 0;
|
|
c < TotalOids;
|
|
c++
|
|
)
|
|
{
|
|
//
|
|
// Is this a statistic Oid?
|
|
//
|
|
if ((OidList[c] & 0x00FF0000) != 0x00020000)
|
|
{
|
|
OidList[CurrentDestOid++] = OidList[c];
|
|
}
|
|
}
|
|
|
|
//
|
|
// If ARCnet then do the filtering.
|
|
//
|
|
if ((Miniport->MediaType == NdisMediumArcnet878_2) &&
|
|
MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION)
|
|
)
|
|
{
|
|
ArcConvertOidListToEthernet(OidList, &CurrentDestOid);
|
|
}
|
|
|
|
//
|
|
// Save the amount of data that was kept.
|
|
//
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
CurrentDestOid * sizeof(NDIS_OID);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMRequestQueryInformationPost(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
switch (Request->DATA.QUERY_INFORMATION.Oid)
|
|
{
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
|
|
//
|
|
// Was this a query for the size of the list?
|
|
//
|
|
if ((NULL == Request->DATA.QUERY_INFORMATION.InformationBuffer) ||
|
|
(0 == Request->DATA.QUERY_INFORMATION.InformationBufferLength) ||
|
|
(Status != NDIS_STATUS_SUCCESS))
|
|
{
|
|
//
|
|
// If this is ARCnet running encapsulated ethernet then
|
|
// we need to add a couple of OIDs to be safe.
|
|
//
|
|
if ((Miniport->MediaType == NdisMediumArcnet878_2) &&
|
|
MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded +=
|
|
(ARC_NUMBER_OF_EXTRA_OIDS * sizeof(NDIS_OID));
|
|
}
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Filter out the statistics oids.
|
|
//
|
|
ndisMFilterOutStatisticsOids(Miniport, Request);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ndisMSyncQueryInformationComplete(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will process a query information complete. This is only
|
|
called from the wrapper. The difference is that this routine will not
|
|
call ndisMProcessDeferred() after processing the completion of the query.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_REQUEST Request;
|
|
PNDIS_M_OPEN_BLOCK Open;
|
|
PNDIS_REQUEST_RESERVED Reserved;
|
|
|
|
//
|
|
// Check for global statistics request
|
|
//
|
|
MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUEST_TIMEOUT);
|
|
|
|
//
|
|
// If the current request is a pointer to the miniport block
|
|
// then this is an initialization request that pended.
|
|
// We complete this by setting the request event.
|
|
//
|
|
if (Miniport->MiniportRequest == (PNDIS_REQUEST)Miniport)
|
|
{
|
|
Miniport->MiniportRequest = NULL;
|
|
Miniport->RequestStatus = Status;
|
|
SET_EVENT(&Miniport->RequestEvent);
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Exit query information complete\n"));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Remove the request.
|
|
//
|
|
Request = Miniport->MiniportRequest;
|
|
Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request);
|
|
Miniport->MiniportRequest = NULL;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Request 0x%x\n", Request));
|
|
|
|
//
|
|
// Separate processing for query statistics information complete.
|
|
//
|
|
if (Request->RequestType == NdisRequestQueryStatistics)
|
|
{
|
|
PNDIS_QUERY_GLOBAL_REQUEST GlobalRequest;
|
|
PNDIS_QUERY_ALL_REQUEST AllRequest;
|
|
PNDIS_QUERY_OPEN_REQUEST OpenRequest;
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Enter Query Statistics Information Complete\n"));
|
|
|
|
GlobalRequest = CONTAINING_RECORD(Request,
|
|
NDIS_QUERY_GLOBAL_REQUEST,
|
|
Request);
|
|
Irp = GlobalRequest->Irp;
|
|
IrpSp = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
switch (IrpSp->MajorFunction)
|
|
{
|
|
case IRP_MJ_CREATE:
|
|
|
|
//
|
|
// This request is one of the ones made during an open,
|
|
// while we are trying to determine the OID list. We
|
|
// set the event we are waiting for, the open code
|
|
// takes care of the rest.
|
|
//
|
|
|
|
OpenRequest = (PNDIS_QUERY_OPEN_REQUEST)GlobalRequest;
|
|
|
|
OpenRequest->NdisStatus = Status;
|
|
SET_EVENT(&OpenRequest->Event);
|
|
|
|
break;
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
|
|
//
|
|
// This is a real user request, process it as such.
|
|
//
|
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_NDIS_QUERY_GLOBAL_STATS:
|
|
|
|
//
|
|
// A single query, complete the IRP.
|
|
//
|
|
Irp->IoStatus.Information =
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten;
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
}
|
|
else if (Status == NDIS_STATUS_INVALID_LENGTH)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
|
|
|
|
FREE_POOL (GlobalRequest);
|
|
|
|
break;
|
|
|
|
case IOCTL_NDIS_QUERY_ALL_STATS:
|
|
|
|
//
|
|
// An "all" query.
|
|
//
|
|
|
|
AllRequest = (PNDIS_QUERY_ALL_REQUEST)GlobalRequest;
|
|
|
|
AllRequest->NdisStatus = Status;
|
|
SET_EVENT(&AllRequest->Event);
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Exit Query Statistics Information Complete\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Do any necessary post-processing on the query.
|
|
//
|
|
ndisMRequestQueryInformationPost(Miniport, Request, Status);
|
|
|
|
//
|
|
// Was this an internal request?
|
|
//
|
|
if (Reserved->Open != NULL)
|
|
{
|
|
//
|
|
// Indicate to Protocol;
|
|
//
|
|
Open = Reserved->Open;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Open 0x%x\n", Open));
|
|
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
|
|
|
|
(Open->ProtocolHandle->ProtocolCharacteristics.RequestCompleteHandler)(
|
|
Open->ProtocolBindingContext,
|
|
Request,
|
|
Status);
|
|
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("- Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
|
|
Open->References--;
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("==0 Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
|
|
if (Open->References == 0)
|
|
{
|
|
ndisMFinishClose(Miniport,Open);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Completing Internal Request\n"));
|
|
|
|
ndisMFreeInternalRequest(Request);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NdisMQueryInformationComplete(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function indicates the completion of a query information operation.
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterHandle - points to the adapter block.
|
|
|
|
Status - Status of the operation
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
|
PSINGLE_LIST_ENTRY Link;
|
|
|
|
ASSERT(MINIPORT_AT_DPC_LEVEL);
|
|
ASSERT(MINIPORT_LOCK_ACQUIRED(Miniport));
|
|
|
|
//
|
|
// If there is no request then we assume this is a complete that was
|
|
// aborted due to the heart-beat.
|
|
//
|
|
if (Miniport->MiniportRequest == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Enter query information complete\n"));
|
|
|
|
//
|
|
// Do the actual processing of the query information complete.
|
|
//
|
|
ndisMSyncQueryInformationComplete(Miniport, Status);
|
|
|
|
//
|
|
// Are there more requests pending?
|
|
//
|
|
if (Miniport->PendingRequest != NULL)
|
|
{
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL, NULL);
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Exit query information complete\n"));
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMRequestSetInformationPost(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will do any necessary post processing for ndis requests
|
|
of the set information type.
|
|
|
|
Arguments:
|
|
|
|
Miniport - Pointer to the miniport block.
|
|
|
|
Request - Pointer to the request to process.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_REQUEST_RESERVED Reserved;
|
|
ULONG GroupAddress;
|
|
|
|
//
|
|
// Get the reserved information for the request.
|
|
//
|
|
Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request);
|
|
|
|
switch (Request->DATA.SET_INFORMATION.Oid)
|
|
{
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
//
|
|
// The request was completed with something besides
|
|
// NDIS_STATUS_SUCCESS (and of course NDIS_STATUS_PENDING).
|
|
// Return the packete filter to the original state.
|
|
//
|
|
Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request);
|
|
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMedium802_3:
|
|
ethUndoFilterAdjust(Miniport->EthDB, Reserved->Open->FilterHandle);
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
trUndoFilterAdjust(Miniport->TrDB, Reserved->Open->FilterHandle);
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
fddiUndoFilterAdjust(Miniport->FddiDB, Reserved->Open->FilterHandle);
|
|
break;
|
|
|
|
case NdisMediumArcnet878_2:
|
|
|
|
if (MINIPORT_TEST_FLAG(Reserved->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
ethUndoFilterAdjust(Miniport->EthDB, Reserved->Open->FilterHandle);
|
|
}
|
|
else
|
|
{
|
|
arcUndoFilterAdjust(Miniport->ArcDB, Reserved->Open->FilterHandle);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
|
|
//
|
|
// If we succeeded then update the binding information.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
NdisMoveMemory(&Reserved->Open->CurrentLookahead,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
4);
|
|
|
|
Miniport->CurrentLookahead = Reserved->Open->CurrentLookahead;
|
|
|
|
Request->DATA.SET_INFORMATION.BytesRead = 4;
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
//
|
|
// We only need to do cleanup if it did not
|
|
// return NDIS_STATUS_SUCCESS.
|
|
//
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
ethUndoChangeFilterAddresses(Miniport->EthDB);
|
|
}
|
|
else
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
trUndoChangeFunctionalAddress(Miniport->TrDB, Reserved->Open->FilterHandle);
|
|
}
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_GROUP:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
trUndoChangeGroupAddress(Miniport->TrDB, Reserved->Open->FilterHandle);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_FDDI_LONG_MULTICAST_LIST:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
fddiUndoChangeFilterLongAddresses(Miniport->FddiDB);
|
|
}
|
|
else
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
break;
|
|
|
|
case OID_FDDI_SHORT_MULTICAST_LIST:
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
fddiUndoChangeFilterShortAddresses(Miniport->FddiDB);
|
|
}
|
|
else
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ndisMSyncSetInformationComplete(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will process a set information complete. This is only
|
|
called from the wrapper. The difference is that this routine will not
|
|
call ndisMProcessDeferred() after processing the completion of the set.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_REQUEST Request;
|
|
PNDIS_M_OPEN_BLOCK Open;
|
|
|
|
//
|
|
// Clear the timeout flag.
|
|
//
|
|
MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUEST_TIMEOUT);
|
|
|
|
//
|
|
// Get a pointer to the request that we are completeing.
|
|
// And clear out the request in-progress pointer.
|
|
//
|
|
Request = Miniport->MiniportRequest;
|
|
Miniport->MiniportRequest = NULL;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Completing Set Information Request 0x%x\n", Request));
|
|
|
|
//
|
|
// Get a pointer to the open that made the request.
|
|
// for internal requests this will be NULL.
|
|
//
|
|
Open = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open;
|
|
|
|
//
|
|
// Do we need to indicate this request to the protocol?
|
|
// We do if it's not an internal request.
|
|
//
|
|
if (Open != NULL)
|
|
{
|
|
//
|
|
// If the open is not closing then notify it of
|
|
// the request completion.
|
|
//
|
|
if (!MINIPORT_TEST_FLAG(Open, fMINIPORT_OPEN_CLOSING))
|
|
{
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Open 0x%x\n", Open));
|
|
|
|
//
|
|
// Do any necessary post processing for the request.
|
|
//
|
|
ndisMRequestSetInformationPost(Miniport, Request, Status);
|
|
|
|
//
|
|
// Indicate to Protocol;
|
|
//
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
|
|
|
|
(Open->ProtocolHandle->ProtocolCharacteristics.RequestCompleteHandler) (
|
|
Open->ProtocolBindingContext,
|
|
Request,
|
|
Status
|
|
);
|
|
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
|
|
}
|
|
|
|
//
|
|
// Dereference the open.
|
|
//
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("- Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
|
|
Open->References--;
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("==0 Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
|
|
if (Open->References == 0)
|
|
{
|
|
ndisMFinishClose(Miniport,Open);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Internal requests are only used for restoring filter settings
|
|
// in the set information path. this means that no post processing
|
|
// needs to be done.
|
|
//
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Completeing internal request\n"));
|
|
|
|
//
|
|
// BUGBUG
|
|
//
|
|
// What if one of these requests fails???? We should probably halt
|
|
// the driver sine this is a fatal error as far as the bindings
|
|
// are concerned.
|
|
//
|
|
ASSERT(NDIS_STATUS_SUCCESS == Status);
|
|
|
|
//
|
|
// Is this the last internal request?
|
|
//
|
|
if (NULL == Miniport->PendingRequest)
|
|
{
|
|
//
|
|
// Now clear out the reset in progress stuff.
|
|
//
|
|
ndisMResetCompleteCommonStep2(Miniport);
|
|
}
|
|
|
|
//
|
|
// Free the request.
|
|
//
|
|
ndisMFreeInternalRequest(Request);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NdisMSetInformationComplete(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function indicates the completion of a set information operation.
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterHandle - points to the adapter block.
|
|
|
|
Status - Status of the operation
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
|
PSINGLE_LIST_ENTRY Link;
|
|
|
|
ASSERT(MINIPORT_AT_DPC_LEVEL);
|
|
ASSERT(MINIPORT_LOCK_ACQUIRED(Miniport));
|
|
|
|
//
|
|
// If we don't have a request to complete assume it was
|
|
// aborted via the reset handler.
|
|
//
|
|
if ((Miniport->MiniportRequest == NULL) ||
|
|
(Miniport->MiniportRequest == (PNDIS_REQUEST)Miniport))
|
|
{
|
|
return;
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Enter set information complete\n"));
|
|
|
|
//
|
|
// Process the actual set information complete.
|
|
//
|
|
ndisMSyncSetInformationComplete(Miniport, Status);
|
|
|
|
//
|
|
// Are there more requests pending?
|
|
//
|
|
if (Miniport->PendingRequest != NULL)
|
|
{
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL, NULL);
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Exit set information complete\n"));
|
|
}
|
|
|
|
VOID
|
|
ndisMAbortQueryStatisticsRequest(
|
|
IN PNDIS_REQUEST Request,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
{
|
|
PNDIS_QUERY_GLOBAL_REQUEST GlobalRequest;
|
|
PNDIS_QUERY_ALL_REQUEST AllRequest;
|
|
PNDIS_QUERY_OPEN_REQUEST OpenRequest;
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
GlobalRequest = CONTAINING_RECORD(Request,
|
|
NDIS_QUERY_GLOBAL_REQUEST,
|
|
Request);
|
|
Irp = GlobalRequest->Irp;
|
|
IrpSp = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
switch (IrpSp->MajorFunction)
|
|
{
|
|
case IRP_MJ_CREATE:
|
|
|
|
//
|
|
// This request is one of the ones made during an open,
|
|
// while we are trying to determine the OID list. We
|
|
// set the event we are waiting for, the open code
|
|
// takes care of the rest.
|
|
//
|
|
|
|
OpenRequest = (PNDIS_QUERY_OPEN_REQUEST)GlobalRequest;
|
|
|
|
OpenRequest->NdisStatus = Status;
|
|
SET_EVENT(&OpenRequest->Event);
|
|
break;
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
|
|
//
|
|
// This is a real user request, process it as such.
|
|
//
|
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_NDIS_QUERY_GLOBAL_STATS:
|
|
//
|
|
// A single query, complete the IRP.
|
|
//
|
|
Irp->IoStatus.Information =
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten;
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
}
|
|
else if (Status == NDIS_STATUS_INVALID_LENGTH)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
|
|
|
|
FREE_POOL (GlobalRequest);
|
|
break;
|
|
|
|
case IOCTL_NDIS_QUERY_ALL_STATS:
|
|
|
|
//
|
|
// An "all" query.
|
|
//
|
|
AllRequest = (PNDIS_QUERY_ALL_REQUEST)GlobalRequest;
|
|
|
|
AllRequest->NdisStatus = Status;
|
|
SET_EVENT(&AllRequest->Event);
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
} // ndisMAbortQueryStatisticsRequest
|
|
|
|
NDIS_STATUS
|
|
ndisMSetPacketFilter(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will process two types of set packet filter requests.
|
|
The first one is for when a reset happens. We simply take the
|
|
packet filter setting that is in the request and send it to the adapter.
|
|
The second is when a protocol sets the packet filter, for this we need
|
|
to update the filter library and then send it down to the adapter.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
ULONG PacketFilter;
|
|
PNDIS_REQUEST_RESERVED Reserved;
|
|
|
|
//
|
|
// Verify the information buffer length that was sent in.
|
|
//
|
|
VERIFY_SET_PARAMETERS(Request, sizeof(PacketFilter), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Now call the filter package to set the
|
|
// packet filter.
|
|
//
|
|
MoveMemory((PVOID)&PacketFilter,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
sizeof(ULONG));
|
|
|
|
//
|
|
// Get a pointer to the reserved information of the request.
|
|
//
|
|
Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request);
|
|
|
|
//
|
|
// If this request is because of an open that is closing then we
|
|
// have already adjusted the filter settings and we just need to
|
|
// make sure that the adapter has the new settings.
|
|
//
|
|
if (MINIPORT_TEST_FLAG(Reserved->Open, fMINIPORT_OPEN_CLOSING))
|
|
{
|
|
//
|
|
// By setting the Status to NDIS_STATUS_PENDING we will call
|
|
// down to the miniport's SetInformationHandler below.
|
|
//
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMedium802_3:
|
|
Status = EthFilterAdjust(Miniport->EthDB,
|
|
Reserved->Open->FilterHandle,
|
|
Request,
|
|
PacketFilter,
|
|
TRUE);
|
|
|
|
//
|
|
// Do this here in anticipation that we
|
|
// need to call down to the miniport
|
|
// driver.
|
|
//
|
|
PacketFilter = ETH_QUERY_FILTER_CLASSES(Miniport->EthDB);
|
|
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
Status = TrFilterAdjust(Miniport->TrDB,
|
|
Reserved->Open->FilterHandle,
|
|
Request,
|
|
PacketFilter,
|
|
TRUE);
|
|
|
|
//
|
|
// Do this here in anticipation that we
|
|
// need to call down to the miniport
|
|
// driver.
|
|
//
|
|
PacketFilter = TR_QUERY_FILTER_CLASSES(Miniport->TrDB);
|
|
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
Status = FddiFilterAdjust(Miniport->FddiDB,
|
|
Reserved->Open->FilterHandle,
|
|
Request,
|
|
PacketFilter,
|
|
TRUE);
|
|
|
|
//
|
|
// Do this here in anticipation that we
|
|
// need to call down to the miniport
|
|
// driver.
|
|
//
|
|
PacketFilter = FDDI_QUERY_FILTER_CLASSES(Miniport->FddiDB);
|
|
|
|
break;
|
|
|
|
case NdisMediumArcnet878_2:
|
|
|
|
if (MINIPORT_TEST_FLAG(Reserved->Open, fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
Status = EthFilterAdjust(Miniport->EthDB,
|
|
Reserved->Open->FilterHandle,
|
|
Request,
|
|
PacketFilter,
|
|
TRUE);
|
|
}
|
|
else
|
|
{
|
|
Status = ArcFilterAdjust(Miniport->ArcDB,
|
|
Reserved->Open->FilterHandle,
|
|
Request,
|
|
PacketFilter,
|
|
TRUE);
|
|
}
|
|
|
|
//
|
|
// Do this here in anticipation that we
|
|
// need to call down to the miniport
|
|
// driver.
|
|
//
|
|
PacketFilter = ARC_QUERY_FILTER_CLASSES(Miniport->ArcDB);
|
|
PacketFilter |= ETH_QUERY_FILTER_CLASSES(Miniport->EthDB);
|
|
|
|
if (MINIPORT_TEST_FLAG(Miniport,
|
|
fMINIPORT_ARCNET_BROADCAST_SET) ||
|
|
(PacketFilter & NDIS_PACKET_TYPE_MULTICAST))
|
|
{
|
|
PacketFilter &= ~NDIS_PACKET_TYPE_MULTICAST;
|
|
PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the filter library returns NDIS_STATUS_PENDING from
|
|
// the XxxFitlerAdjust() then we need to call down to the
|
|
// miniport driver. Other wise this will have succeeded.
|
|
//
|
|
if (NDIS_STATUS_PENDING == Status)
|
|
{
|
|
//
|
|
// Save the current global packet filter in a buffer that will stick around.
|
|
// Remove the ALL_LOCAL bit since miniport does not understand this (and does
|
|
// not need to).
|
|
//
|
|
*(UNALIGNED ULONG *)(Miniport->MulticastBuffer) = PacketFilter & ~NDIS_PACKET_TYPE_ALL_LOCAL;
|
|
|
|
//
|
|
// If the local-only bit is set and the miniport is doing it's own
|
|
// loop back then we need to make sure that we loop back non-self
|
|
// directed packets that are sent out on the pipe.
|
|
//
|
|
if ((PacketFilter & NDIS_PACKET_TYPE_ALL_LOCAL) &&
|
|
(Miniport->MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) == 0)
|
|
{
|
|
MINIPORT_SET_SEND_FLAG(Miniport, fMINIPORT_SEND_LOOPBACK_DIRECTED);
|
|
}
|
|
else
|
|
{
|
|
MINIPORT_CLEAR_SEND_FLAG(Miniport, fMINIPORT_SEND_LOOPBACK_DIRECTED);
|
|
}
|
|
|
|
//
|
|
// Call the miniport driver.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
OID_GEN_CURRENT_PACKET_FILTER,
|
|
Miniport->MulticastBuffer,
|
|
sizeof(PacketFilter),
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
}
|
|
|
|
//
|
|
// If we have success then set the Bytes read in the original request.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 4;
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMSetCurrentLookahead(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
UINT Lookahead;
|
|
ULONG CurrentMax;
|
|
PNDIS_M_OPEN_BLOCK CurrentOpen;
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Verify length of the information buffer.
|
|
//
|
|
VERIFY_SET_PARAMETERS(Request, sizeof(Lookahead), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Put the lookahead that the binding requests into a
|
|
// buffer we can use...
|
|
//
|
|
MoveMemory(&Lookahead,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
sizeof(Lookahead));
|
|
|
|
//
|
|
// Verify that the lookahead is within boundaries...
|
|
//
|
|
if (Lookahead > Miniport->MaximumLookahead)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_INVALID_LENGTH);
|
|
}
|
|
|
|
//
|
|
// Find the maximum lookahead between all opens that
|
|
// are bound to the miniport driver.
|
|
//
|
|
for (CurrentOpen = Miniport->OpenQueue, CurrentMax = 0;
|
|
CurrentOpen != NULL;
|
|
CurrentOpen = CurrentOpen->MiniportNextOpen)
|
|
{
|
|
if (CurrentOpen->CurrentLookahead > CurrentMax)
|
|
{
|
|
CurrentMax = CurrentOpen->CurrentLookahead;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Figure in the new lookahead.
|
|
//
|
|
if (Lookahead > CurrentMax)
|
|
{
|
|
CurrentMax = Lookahead;
|
|
}
|
|
|
|
//
|
|
// Adjust the current max lookahead if needed.
|
|
//
|
|
if (CurrentMax == 0)
|
|
{
|
|
CurrentMax = Miniport->MaximumLookahead;
|
|
}
|
|
|
|
//
|
|
// Set the default status.
|
|
//
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// Do we need to call the miniport driver with the
|
|
// new max lookahead?
|
|
//
|
|
if (Miniport->CurrentLookahead != CurrentMax)
|
|
{
|
|
//
|
|
// Save the new lookahead value in a buffer
|
|
// that will stick around.
|
|
//
|
|
MoveMemory(Miniport->MulticastBuffer,
|
|
&CurrentMax,
|
|
sizeof(CurrentMax));
|
|
|
|
//
|
|
// Send it to the driver.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
OID_GEN_CURRENT_LOOKAHEAD,
|
|
Miniport->MulticastBuffer,
|
|
sizeof(CurrentMax),
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
}
|
|
|
|
//
|
|
// If we succeeded then update the binding information.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->CurrentLookahead = Lookahead;
|
|
Request->DATA.SET_INFORMATION.BytesRead = sizeof(Lookahead);
|
|
Miniport->CurrentLookahead = CurrentMax;
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMSetMulticastList(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
UINT NumberOfAddresses;
|
|
NDIS_STATUS Status;
|
|
PNDIS_REQUEST_RESERVED Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request);
|
|
|
|
//
|
|
// If the media type is not Ethernet or Ethernet encapsulated ARCnet
|
|
// then bail.
|
|
//
|
|
if ((Miniport->MediaType != NdisMedium802_3) &&
|
|
!((Miniport->MediaType == NdisMediumArcnet878_2) &&
|
|
MINIPORT_TEST_FLAG(Reserved->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION)))
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_NOT_SUPPORTED);
|
|
}
|
|
|
|
//
|
|
// Verify the information buffer length that was passed in.
|
|
//
|
|
if ((Request->DATA.SET_INFORMATION.InformationBufferLength % ETH_LENGTH_OF_ADDRESS) != 0)
|
|
{
|
|
//
|
|
// The data must be a multiple of the Ethernet
|
|
// address size.
|
|
//
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_INVALID_DATA);
|
|
}
|
|
|
|
//
|
|
// If this request is because of an open that is closing then we
|
|
// have already adjusted the settings and we just need to
|
|
// make sure that the adapter has the new settings.
|
|
//
|
|
if (MINIPORT_TEST_FLAG(Reserved->Open, fMINIPORT_OPEN_CLOSING))
|
|
{
|
|
//
|
|
// By setting the Status to NDIS_STATUS_PENDING we will call
|
|
// down to the miniport's SetInformationHandler below.
|
|
//
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Call the filter library for a normal set operation.
|
|
//
|
|
Status = EthChangeFilterAddresses(
|
|
Miniport->EthDB,
|
|
Reserved->Open->FilterHandle,
|
|
Request,
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength / ETH_LENGTH_OF_ADDRESS,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
TRUE);
|
|
}
|
|
|
|
//
|
|
// If the filter library returned pending then we need to
|
|
// call the miniport driver.
|
|
//
|
|
if (NDIS_STATUS_PENDING == Status)
|
|
{
|
|
//
|
|
// Get a list of all the multicast address that need
|
|
// to be set.
|
|
//
|
|
EthQueryGlobalFilterAddresses(
|
|
&Status,
|
|
Miniport->EthDB,
|
|
NDIS_M_MAX_MULTI_LIST * ETH_LENGTH_OF_ADDRESS,
|
|
&NumberOfAddresses,
|
|
(PVOID)Miniport->MulticastBuffer);
|
|
|
|
//
|
|
// Call the driver with the new multicast list.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
OID_802_3_MULTICAST_LIST,
|
|
Miniport->MulticastBuffer,
|
|
NumberOfAddresses * ETH_LENGTH_OF_ADDRESS,
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
}
|
|
|
|
//
|
|
// If we succeeded then update the request.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMSetFunctionalAddress(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT FunctionalAddress;
|
|
|
|
//
|
|
// Verify the media type.
|
|
//
|
|
if (Miniport->MediaType != NdisMedium802_5)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_NOT_SUPPORTED);
|
|
}
|
|
|
|
//
|
|
// Verify the buffer length that was passed in.
|
|
//
|
|
VERIFY_SET_PARAMETERS(Request, sizeof(FunctionalAddress), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// If this request is because of an open that is closing then we
|
|
// have already adjusted the settings and we just need to
|
|
// make sure that the adapter has the new settings.
|
|
//
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open, fMINIPORT_OPEN_CLOSING))
|
|
{
|
|
//
|
|
// By setting the Status to NDIS_STATUS_PENDING we will call
|
|
// down to the miniport's SetInformationHandler below.
|
|
//
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Call the filter library to set the functional address.
|
|
//
|
|
Status = TrChangeFunctionalAddress(
|
|
Miniport->TrDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request,
|
|
(PUCHAR)(Request->DATA.SET_INFORMATION.InformationBuffer),
|
|
TRUE);
|
|
}
|
|
|
|
//
|
|
// If the filter library returned NDIS_STATUS_PENDING then we
|
|
// need to call down to the miniport driver.
|
|
//
|
|
if (NDIS_STATUS_PENDING == Status)
|
|
{
|
|
//
|
|
// Get the new combined functional address from the filter library
|
|
// and save it in a buffer that will stick around.
|
|
//
|
|
FunctionalAddress = TR_QUERY_FILTER_ADDRESSES(Miniport->TrDB);
|
|
FunctionalAddress = BYTE_SWAP_ULONG(FunctionalAddress);
|
|
MoveMemory(Miniport->MulticastBuffer,
|
|
&FunctionalAddress,
|
|
sizeof(FunctionalAddress));
|
|
|
|
//
|
|
// Call the miniport driver.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
OID_802_5_CURRENT_FUNCTIONAL,
|
|
Miniport->MulticastBuffer,
|
|
sizeof(FunctionalAddress),
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
}
|
|
|
|
//
|
|
// If we succeeded then update the request.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMSetGroupAddress(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT GroupAddress;
|
|
|
|
//
|
|
// Verify the media type.
|
|
//
|
|
if (Miniport->MediaType != NdisMedium802_5)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_NOT_SUPPORTED);
|
|
}
|
|
|
|
//
|
|
// Verify the information buffer length.
|
|
//
|
|
VERIFY_SET_PARAMETERS(Request, sizeof(GroupAddress), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// If this request is because of an open that is closing then we
|
|
// have already adjusted the settings and we just need to
|
|
// make sure that the adapter has the new settings.
|
|
//
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open, fMINIPORT_OPEN_CLOSING))
|
|
{
|
|
//
|
|
// By setting the Status to NDIS_STATUS_PENDING we will call
|
|
// down to the miniport's SetInformationHandler below.
|
|
//
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Call the filter library to set the new group address.
|
|
//
|
|
Status = TrChangeGroupAddress(
|
|
Miniport->TrDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request,
|
|
(PUCHAR)(Request->DATA.SET_INFORMATION.InformationBuffer),
|
|
TRUE);
|
|
}
|
|
|
|
//
|
|
// If the filter library returned NDIS_STATUS_PENDING then we
|
|
// need to call down to the miniport driver.
|
|
//
|
|
if (NDIS_STATUS_PENDING == Status)
|
|
{
|
|
//
|
|
// Get the new group address from the filter library
|
|
// and save it in a buffer that will stick around.
|
|
//
|
|
GroupAddress = TR_QUERY_FILTER_GROUP(Miniport->TrDB);
|
|
GroupAddress = BYTE_SWAP_ULONG(GroupAddress);
|
|
MoveMemory(Miniport->MulticastBuffer,
|
|
&GroupAddress,
|
|
sizeof(GroupAddress));
|
|
|
|
//
|
|
// Call the miniport driver with the new group address.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
OID_802_5_CURRENT_GROUP,
|
|
Miniport->MulticastBuffer,
|
|
sizeof(GroupAddress),
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
}
|
|
|
|
//
|
|
// If we succeeded then update the request.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMSetFddiMulticastList(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request,
|
|
IN BOOLEAN fShort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT NumberOfAddresses, AddrLen;
|
|
|
|
AddrLen = FDDI_LENGTH_OF_LONG_ADDRESS;
|
|
if (fShort)
|
|
{
|
|
AddrLen = FDDI_LENGTH_OF_SHORT_ADDRESS;
|
|
}
|
|
//
|
|
// Verify the media type.
|
|
//
|
|
if (Miniport->MediaType != NdisMediumFddi)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_NOT_SUPPORTED);
|
|
}
|
|
|
|
//
|
|
// Verify the information buffer length.
|
|
//
|
|
if ((Request->DATA.SET_INFORMATION.InformationBufferLength % AddrLen) != 0)
|
|
{
|
|
//
|
|
// The data must be a multiple of the Ethernet
|
|
// address size.
|
|
//
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
|
|
return(NDIS_STATUS_INVALID_DATA);
|
|
}
|
|
|
|
//
|
|
// If this request is because of an open that is closing then we
|
|
// have already adjusted the settings and we just need to
|
|
// make sure that the adapter has the new settings.
|
|
//
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open, fMINIPORT_OPEN_CLOSING))
|
|
{
|
|
//
|
|
// By setting the Status to NDIS_STATUS_PENDING we will call
|
|
// down to the miniport's SetInformationHandler below.
|
|
//
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Now call the filter package to set up the addresses.
|
|
//
|
|
Status = fShort ?
|
|
FddiChangeFilterShortAddresses(
|
|
Miniport->FddiDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request,
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength / AddrLen,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
TRUE) :
|
|
FddiChangeFilterLongAddresses(
|
|
Miniport->FddiDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request,
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength / AddrLen,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
TRUE);
|
|
}
|
|
|
|
//
|
|
// If the filter library returned NDIS_STATUS_PENDING then we
|
|
// need to call down to the miniport driver.
|
|
//
|
|
if (NDIS_STATUS_PENDING == Status)
|
|
{
|
|
//
|
|
// Get the number of multicast addresses and the list
|
|
// of multicast addresses to send to the miniport driver.
|
|
//
|
|
fShort ?
|
|
FddiQueryGlobalFilterShortAddresses(&Status,
|
|
Miniport->FddiDB,
|
|
NDIS_M_MAX_MULTI_LIST * AddrLen,
|
|
&NumberOfAddresses,
|
|
(PVOID)Miniport->MulticastBuffer) :
|
|
FddiQueryGlobalFilterLongAddresses( &Status,
|
|
Miniport->FddiDB,
|
|
NDIS_M_MAX_MULTI_LIST * AddrLen,
|
|
&NumberOfAddresses,
|
|
(PVOID)Miniport->MulticastBuffer);
|
|
|
|
//
|
|
// Call the miniport driver.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
fShort ? OID_FDDI_SHORT_MULTICAST_LIST : OID_FDDI_LONG_MULTICAST_LIST,
|
|
Miniport->MulticastBuffer,
|
|
NumberOfAddresses * AddrLen,
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
}
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead =
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength;
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
Request->DATA.SET_INFORMATION.BytesRead = 0;
|
|
Request->DATA.SET_INFORMATION.BytesNeeded = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMSetInformation(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// If there is no open associated with the request
|
|
// then it is an internal request and we just send it down
|
|
// to the adapter.
|
|
//
|
|
if (PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open == NULL)
|
|
{
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Request->DATA.SET_INFORMATION.Oid,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength,
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Process the binding's request.
|
|
//
|
|
switch (Request->DATA.SET_INFORMATION.Oid)
|
|
{
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
|
|
//
|
|
// Set the packet filter.
|
|
//
|
|
Status = ndisMSetPacketFilter(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
|
|
//
|
|
// Set the current look ahead for the miniport.
|
|
//
|
|
Status = ndisMSetCurrentLookahead(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_GEN_PROTOCOL_OPTIONS:
|
|
|
|
VERIFY_SET_PARAMETERS(Request, sizeof(ULONG), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Copy the protocol options into the open block.
|
|
//
|
|
MoveMemory(&PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->ProtocolOptions,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
sizeof(ULONG));
|
|
|
|
Request->DATA.SET_INFORMATION.BytesRead = sizeof(ULONG);
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
//
|
|
// Set the ethernet multicast list.
|
|
//
|
|
Status = ndisMSetMulticastList(Miniport, Request);
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
|
|
//
|
|
// Set the token ring functional address.
|
|
//
|
|
Status = ndisMSetFunctionalAddress(Miniport, Request);
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_GROUP:
|
|
|
|
//
|
|
// Set the token ring group address.
|
|
//
|
|
Status = ndisMSetGroupAddress(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_FDDI_LONG_MULTICAST_LIST:
|
|
|
|
//
|
|
// Set the FDDI long multicast list.
|
|
//
|
|
Status = ndisMSetFddiMulticastList(Miniport, Request, FALSE);
|
|
|
|
break;
|
|
|
|
case OID_FDDI_SHORT_MULTICAST_LIST:
|
|
|
|
//
|
|
// Set the FDDI short multicast list.
|
|
//
|
|
Status = ndisMSetFddiMulticastList(Miniport, Request, TRUE);
|
|
|
|
break;
|
|
|
|
default:
|
|
Status =
|
|
(Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Request->DATA.SET_INFORMATION.Oid,
|
|
Request->DATA.SET_INFORMATION.InformationBuffer,
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength,
|
|
&Request->DATA.SET_INFORMATION.BytesRead,
|
|
&Request->DATA.SET_INFORMATION.BytesNeeded);
|
|
break;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryCurrentPacketFilter(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
ULONG PacketFilter;
|
|
NDIS_HANDLE FilterHandle;
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Verify the buffer that was passed to us.
|
|
//
|
|
VERIFY_QUERY_PARAMETERS(Request, sizeof(PacketFilter), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Get the filter handle from the open block.
|
|
//
|
|
FilterHandle = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle;
|
|
|
|
//
|
|
// Get the packet filter from the filter library.
|
|
//
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMedium802_3:
|
|
PacketFilter = ETH_QUERY_PACKET_FILTER(Miniport->EthDB, FilterHandle);
|
|
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
PacketFilter = TR_QUERY_PACKET_FILTER(Miniport->TrDB, FilterHandle);
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
PacketFilter = FDDI_QUERY_PACKET_FILTER(Miniport->FddiDB, FilterHandle);
|
|
break;
|
|
|
|
case NdisMediumArcnet878_2:
|
|
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
PacketFilter = ETH_QUERY_PACKET_FILTER(Miniport->EthDB, FilterHandle);
|
|
}
|
|
else
|
|
{
|
|
PacketFilter = ARC_QUERY_PACKET_FILTER(Miniport->ArcDB, FilterHandle);
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Place the packet filter in the buffer that was passed in.
|
|
//
|
|
MoveMemory(Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
&PacketFilter,
|
|
sizeof(PacketFilter));
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(PacketFilter);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryMediaSupported(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
ULONG MediaType;
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Verify the size of the buffer that was passed in by the binding.
|
|
//
|
|
VERIFY_QUERY_PARAMETERS(Request, sizeof(MediaType), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Default the media type to what the miniport knows it is.
|
|
//
|
|
MediaType = (ULONG)Miniport->MediaType;
|
|
|
|
//
|
|
// If we are doing ethernet encapsulation then lie.
|
|
//
|
|
if ((NdisMediumArcnet878_2 == Miniport->MediaType) &&
|
|
MINIPORT_TEST_FLAG(PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
//
|
|
// Tell the binding that we are ethernet.
|
|
//
|
|
MediaType = (ULONG)NdisMedium802_3;
|
|
}
|
|
|
|
//
|
|
// Save it in the request.
|
|
//
|
|
MoveMemory(Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
&MediaType,
|
|
sizeof(MediaType));
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(MediaType);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryEthernetMulticastList(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT NumberOfAddresses;
|
|
|
|
//
|
|
// call the filter library to get the list of multicast
|
|
// addresses for this open
|
|
//
|
|
EthQueryOpenFilterAddresses(&Status,
|
|
Miniport->EthDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&NumberOfAddresses,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
//
|
|
// If the library returned NDIS_STATUS_FAILURE then the buffer
|
|
// was not big enough. So call back down to determine how
|
|
// much buffer space we need.
|
|
//
|
|
if (NDIS_STATUS_FAILURE == Status)
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded =
|
|
ETH_LENGTH_OF_ADDRESS *
|
|
EthNumberOfOpenFilterAddresses(
|
|
Miniport->EthDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle);
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
|
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
NumberOfAddresses * ETH_LENGTH_OF_ADDRESS;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryLongMulticastList(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT NumberOfAddresses;
|
|
|
|
//
|
|
// Call the filter library to get the list of long
|
|
// multicast address for this open.
|
|
//
|
|
FddiQueryOpenFilterLongAddresses(
|
|
&Status,
|
|
Miniport->FddiDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&NumberOfAddresses,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
|
|
//
|
|
// If the library returned NDIS_STATUS_FAILURE then the buffer
|
|
// was not big enough. So call back down to determine how
|
|
// much buffer space we need.
|
|
//
|
|
if (NDIS_STATUS_FAILURE == Status)
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded =
|
|
FDDI_LENGTH_OF_LONG_ADDRESS *
|
|
FddiNumberOfOpenFilterLongAddresses(
|
|
Miniport->FddiDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle);
|
|
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
|
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
NumberOfAddresses * FDDI_LENGTH_OF_LONG_ADDRESS;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryShortMulticastList(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT NumberOfAddresses;
|
|
|
|
//
|
|
// Call the filter library to get the list of long
|
|
// multicast address for this open.
|
|
//
|
|
FddiQueryOpenFilterShortAddresses(
|
|
&Status,
|
|
Miniport->FddiDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&NumberOfAddresses,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
|
|
//
|
|
// If the library returned NDIS_STATUS_FAILURE then the buffer
|
|
// was not big enough. So call back down to determine how
|
|
// much buffer space we need.
|
|
//
|
|
if (NDIS_STATUS_FAILURE == Status)
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded =
|
|
FDDI_LENGTH_OF_SHORT_ADDRESS *
|
|
FddiNumberOfOpenFilterShortAddresses(
|
|
Miniport->FddiDB,
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open->FilterHandle);
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
|
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
Request->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
NumberOfAddresses * FDDI_LENGTH_OF_SHORT_ADDRESS;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryMaximumFrameSize(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PULONG pulBuffer = Request->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
|
|
VERIFY_QUERY_PARAMETERS(Request, sizeof(*pulBuffer), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Is this ARCnet using encapsulated ethernet?
|
|
//
|
|
if (Miniport->MediaType == NdisMediumArcnet878_2)
|
|
{
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
//
|
|
// 504 - 14 (ethernet header) == 490.
|
|
//
|
|
*pulBuffer = ARC_MAX_FRAME_SIZE - 14;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(*pulBuffer);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the miniport for the information.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Request->DATA.QUERY_INFORMATION.Oid,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&(Request->DATA.QUERY_INFORMATION.BytesWritten),
|
|
&(Request->DATA.QUERY_INFORMATION.BytesNeeded));
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryMaximumTotalSize(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PULONG pulBuffer = Request->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
|
|
VERIFY_QUERY_PARAMETERS(Request, sizeof(*pulBuffer), Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Is this ARCnet using encapsulated ethernet?
|
|
//
|
|
if (Miniport->MediaType == NdisMediumArcnet878_2)
|
|
{
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
*pulBuffer = ARC_MAX_FRAME_SIZE;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(*pulBuffer);
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the miniport for the information.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Request->DATA.QUERY_INFORMATION.Oid,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&(Request->DATA.QUERY_INFORMATION.BytesWritten),
|
|
&(Request->DATA.QUERY_INFORMATION.BytesNeeded));
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryNetworkAddress(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
UCHAR Address[ETH_LENGTH_OF_ADDRESS];
|
|
|
|
VERIFY_QUERY_PARAMETERS(Request, ETH_LENGTH_OF_ADDRESS, Status);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Is this ARCnet using encapsulated ethernet?
|
|
//
|
|
if (Miniport->MediaType == NdisMediumArcnet878_2)
|
|
{
|
|
if (MINIPORT_TEST_FLAG(
|
|
PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open,
|
|
fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
//
|
|
// Arcnet-to-ethernet conversion.
|
|
//
|
|
ZeroMemory(Address, ETH_LENGTH_OF_ADDRESS);
|
|
|
|
Address[5] = Miniport->ArcnetAddress;
|
|
|
|
MoveMemory(Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
Address,
|
|
ETH_LENGTH_OF_ADDRESS);
|
|
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten = ETH_LENGTH_OF_ADDRESS;
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the miniport for the information.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Request->DATA.QUERY_INFORMATION.Oid,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&(Request->DATA.QUERY_INFORMATION.BytesWritten),
|
|
&(Request->DATA.QUERY_INFORMATION.BytesNeeded)
|
|
);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMQueryInformation(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_REQUEST Request
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PVOID Buffer;
|
|
PULONG pulBuffer;
|
|
ULONG BufferLength;
|
|
PNDIS_M_OPEN_BLOCK Open;
|
|
ULONG Generic;
|
|
|
|
//
|
|
// Copy the request information into temporary storage.
|
|
//
|
|
Buffer = Request->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
pulBuffer = Buffer;
|
|
BufferLength = Request->DATA.QUERY_INFORMATION.InformationBufferLength;
|
|
|
|
Open = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Open;
|
|
|
|
//
|
|
// We intercept some calls.
|
|
//
|
|
switch (Request->DATA.QUERY_INFORMATION.Oid)
|
|
{
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
|
|
Status = ndisMQueryCurrentPacketFilter(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
|
|
Status = ndisMQueryMediaSupported(Miniport, Request);
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(Open->CurrentLookahead),
|
|
Status);
|
|
|
|
//
|
|
// Save the lookahead in the binding's buffer.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
*pulBuffer = Open->CurrentLookahead;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(Open->CurrentLookahead);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(Miniport->MaximumLookahead),
|
|
Status);
|
|
|
|
//
|
|
// Save the lookahead in the binding's buffer.
|
|
//
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
*pulBuffer = Miniport->MaximumLookahead;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(Miniport->MaximumLookahead);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
Status = ndisMQueryEthernetMulticastList(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(Miniport->MaximumLongAddresses),
|
|
Status);
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
*pulBuffer = Miniport->MaximumLongAddresses;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(Miniport->MaximumLongAddresses);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(*pulBuffer),
|
|
Status);
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
Generic = TR_QUERY_FILTER_BINDING_ADDRESS(
|
|
Miniport->TrDB,
|
|
Open->FilterHandle
|
|
);
|
|
|
|
*pulBuffer = BYTE_SWAP_ULONG(Generic);
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(*pulBuffer);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_GROUP:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(*pulBuffer),
|
|
Status);
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
*pulBuffer = TR_QUERY_FILTER_GROUP(Miniport->TrDB);
|
|
*pulBuffer = BYTE_SWAP_ULONG(*pulBuffer);
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(*pulBuffer);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_FDDI_LONG_MULTICAST_LIST:
|
|
|
|
Status = ndisMQueryLongMulticastList(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_FDDI_LONG_MAX_LIST_SIZE:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(*pulBuffer),
|
|
Status);
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
*pulBuffer = Miniport->MaximumLongAddresses;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(*pulBuffer);
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_FDDI_SHORT_MULTICAST_LIST:
|
|
|
|
Status = ndisMQueryShortMulticastList(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_FDDI_SHORT_MAX_LIST_SIZE:
|
|
|
|
VERIFY_QUERY_PARAMETERS(
|
|
Request,
|
|
sizeof(Miniport->MaximumShortAddresses),
|
|
Status);
|
|
|
|
if (NDIS_STATUS_SUCCESS == Status)
|
|
{
|
|
*pulBuffer = Miniport->MaximumShortAddresses;
|
|
Request->DATA.QUERY_INFORMATION.BytesWritten =
|
|
sizeof(Miniport->MaximumShortAddresses);
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// Start interceptions for running an ethernet
|
|
// protocol on top of an arcnet mini-port.
|
|
//
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
|
|
Status = ndisMQueryMaximumFrameSize(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
|
|
Status = ndisMQueryMaximumTotalSize(Miniport, Request);
|
|
|
|
break;
|
|
|
|
case OID_802_3_PERMANENT_ADDRESS:
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
|
|
Status = ndisMQueryNetworkAddress(Miniport, Request);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// We don't filter this request, just pass it down
|
|
// to the driver.
|
|
//
|
|
Status = (Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
Request->DATA.QUERY_INFORMATION.Oid,
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&Request->DATA.QUERY_INFORMATION.BytesWritten,
|
|
&Request->DATA.QUERY_INFORMATION.BytesNeeded);
|
|
|
|
break;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMDoRequests(
|
|
IN PNDIS_MINIPORT_BLOCK Miniport
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Submits a request to the mini-port.
|
|
|
|
Arguments:
|
|
|
|
Miniport - Miniport to send to.
|
|
|
|
Return Value:
|
|
|
|
TRUE if we need to place the work item back on the queue to process later.
|
|
FALSE if we are done with the work item.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Enter do requests\n"));
|
|
|
|
ASSERT(MINIPORT_AT_DPC_LEVEL);
|
|
ASSERT(MINIPORT_LOCK_ACQUIRED(Miniport));
|
|
|
|
//
|
|
// Do we have a request in progress?
|
|
//
|
|
while ((Miniport->MiniportRequest == NULL) && (Miniport->PendingRequest != NULL))
|
|
{
|
|
PNDIS_REQUEST_RESERVED Reserved;
|
|
PNDIS_REQUEST NdisRequest;
|
|
UINT MulticastAddresses;
|
|
ULONG PacketFilter;
|
|
BOOLEAN DoMove;
|
|
PVOID MoveSource;
|
|
UINT MoveBytes;
|
|
ULONG GenericULong;
|
|
|
|
//
|
|
// Set defaults.
|
|
//
|
|
DoMove = TRUE;
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// Remove first request
|
|
//
|
|
NdisRequest = Miniport->PendingRequest;
|
|
Miniport->PendingRequest = PNDIS_RESERVED_FROM_PNDIS_REQUEST(NdisRequest)->Next;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Starting protocol request 0x%x\n", NdisRequest));
|
|
|
|
//
|
|
// Clear the timeout flag.
|
|
//
|
|
MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUEST_TIMEOUT);
|
|
|
|
//
|
|
// Put it on mini-port queue
|
|
//
|
|
Miniport->MiniportRequest = NdisRequest;
|
|
|
|
//
|
|
// Submit to mini-port
|
|
//
|
|
switch (NdisRequest->RequestType)
|
|
{
|
|
case NdisRequestQueryInformation:
|
|
|
|
//
|
|
// Process the query information.
|
|
//
|
|
Status = ndisMQueryInformation(Miniport, NdisRequest);
|
|
|
|
break;
|
|
|
|
case NdisRequestQueryStatistics:
|
|
|
|
//
|
|
// Query GLOBAL statistics
|
|
//
|
|
MoveSource = &GenericULong;
|
|
MoveBytes = sizeof(GenericULong);
|
|
|
|
//
|
|
// We intercept some calls
|
|
//
|
|
|
|
switch (NdisRequest->DATA.QUERY_INFORMATION.Oid)
|
|
{
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMedium802_3:
|
|
PacketFilter = ETH_QUERY_FILTER_CLASSES(Miniport->EthDB);
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
PacketFilter = TR_QUERY_FILTER_CLASSES(Miniport->TrDB);
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
PacketFilter = FDDI_QUERY_FILTER_CLASSES(Miniport->FddiDB);
|
|
break;
|
|
|
|
case NdisMediumArcnet878_2:
|
|
PacketFilter = ARC_QUERY_FILTER_CLASSES(Miniport->ArcDB);
|
|
PacketFilter |= ETH_QUERY_FILTER_CLASSES(Miniport->EthDB);
|
|
break;
|
|
}
|
|
|
|
GenericULong = (ULONG)(PacketFilter);
|
|
break;
|
|
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
MoveSource = (PVOID) (&Miniport->MediaType);
|
|
MoveBytes = sizeof(NDIS_MEDIUM);
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
GenericULong = (ULONG)(Miniport->CurrentLookahead);
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
GenericULong = (ULONG)(Miniport->MaximumLookahead);
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
EthQueryGlobalFilterAddresses(
|
|
&Status,
|
|
Miniport->EthDB,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&MulticastAddresses,
|
|
(PVOID)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer));
|
|
|
|
MoveSource = (PVOID)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
MoveBytes = MulticastAddresses * ETH_LENGTH_OF_ADDRESS;
|
|
break;
|
|
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
GenericULong = Miniport->MaximumLongAddresses;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
GenericULong = TR_QUERY_FILTER_ADDRESSES(Miniport->TrDB);
|
|
GenericULong = BYTE_SWAP_ULONG(GenericULong);
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_GROUP:
|
|
GenericULong = TR_QUERY_FILTER_GROUP(Miniport->TrDB);
|
|
GenericULong = BYTE_SWAP_ULONG(GenericULong);
|
|
break;
|
|
|
|
case OID_FDDI_LONG_MULTICAST_LIST:
|
|
FddiQueryGlobalFilterLongAddresses(
|
|
&Status,
|
|
Miniport->FddiDB,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&MulticastAddresses,
|
|
(PVOID)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
MoveSource = (PVOID)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
MoveBytes = FDDI_LENGTH_OF_LONG_ADDRESS * MulticastAddresses;
|
|
break;
|
|
|
|
case OID_FDDI_LONG_MAX_LIST_SIZE:
|
|
GenericULong = Miniport->MaximumLongAddresses;
|
|
break;
|
|
|
|
case OID_FDDI_SHORT_MULTICAST_LIST:
|
|
FddiQueryGlobalFilterShortAddresses(
|
|
&Status,
|
|
Miniport->FddiDB,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&MulticastAddresses,
|
|
(PVOID)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
|
|
|
|
MoveSource = (PVOID)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
|
|
MoveBytes = FDDI_LENGTH_OF_SHORT_ADDRESS * MulticastAddresses;
|
|
break;
|
|
|
|
case OID_FDDI_SHORT_MAX_LIST_SIZE:
|
|
GenericULong = Miniport->MaximumShortAddresses;
|
|
break;
|
|
|
|
default:
|
|
DoMove = FALSE;
|
|
|
|
Status =
|
|
(Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
|
|
Miniport->MiniportAdapterContext,
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
|
|
&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
|
|
break;
|
|
}
|
|
|
|
if (DoMove)
|
|
{
|
|
//
|
|
// This was an intercepted request. Finish it off
|
|
//
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (MoveBytes >
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength)
|
|
{
|
|
//
|
|
// Not enough room in InformationBuffer. Punt
|
|
//
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = MoveBytes;
|
|
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Copy result into InformationBuffer
|
|
//
|
|
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = MoveBytes;
|
|
|
|
if ((MoveBytes > 0) &&
|
|
(MoveSource != NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer))
|
|
{
|
|
MoveMemory(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
MoveSource,
|
|
MoveBytes);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = MoveBytes;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NdisRequestSetInformation:
|
|
|
|
//
|
|
// Process the set infromation.
|
|
//
|
|
Status = ndisMSetInformation(Miniport, NdisRequest);
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Did the request pend? If so then there is nothing more to do.
|
|
//
|
|
if ((Status == NDIS_STATUS_PENDING) &&
|
|
(Miniport->MiniportRequest != NULL))
|
|
{
|
|
//
|
|
// Still outstanding
|
|
//
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Request pending, exit do requests\n"));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Complete request
|
|
//
|
|
if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
switch (NdisRequest->RequestType)
|
|
{
|
|
case NdisRequestQueryStatistics:
|
|
case NdisRequestQueryInformation:
|
|
|
|
ndisMSyncQueryInformationComplete(Miniport, Status);
|
|
break;
|
|
|
|
case NdisRequestSetInformation:
|
|
|
|
ndisMSyncSetInformationComplete(Miniport, Status);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Exit do requests\n"));
|
|
}
|
|
|
|
//
|
|
// IRP handlers established on behalf of NDIS devices by
|
|
// the wrapper.
|
|
//
|
|
|
|
NTSTATUS
|
|
ndisMQueryOidList(
|
|
IN PNDIS_USER_OPEN_CONTEXT OpenContext,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will take care of querying the complete OID
|
|
list for the driver and filling in OpenContext->OidArray
|
|
with the ones that are statistics. It blocks when the
|
|
driver pends and so is synchronous.
|
|
|
|
Arguments:
|
|
|
|
OpenContext - The open context.
|
|
Irp = The IRP that the open was done on (used at completion
|
|
to distinguish the request).
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if it should be.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_QUERY_OPEN_REQUEST OpenRequest;
|
|
NDIS_STATUS NdisStatus;
|
|
PNDIS_OID TmpBuffer;
|
|
ULONG TmpBufferLength;
|
|
PNDIS_REQUEST_RESERVED Reserved;
|
|
BOOLEAN LocalLock;
|
|
PNDIS_MINIPORT_BLOCK Miniport = OpenContext->MiniportBlock;
|
|
KIRQL OldIrql;
|
|
PSINGLE_LIST_ENTRY Link;
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Enter query oid list\n"));
|
|
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
|
|
LOCK_MINIPORT(Miniport, LocalLock);
|
|
|
|
do
|
|
{
|
|
//
|
|
// First query the OID list with no buffer, to find out
|
|
// how big it should be.
|
|
//
|
|
|
|
INITIALIZE_EVENT(&OpenRequest.Event);
|
|
|
|
OpenRequest.Irp = Irp;
|
|
|
|
//
|
|
// Build fake request
|
|
//
|
|
|
|
OpenRequest.Request.RequestType = NdisRequestQueryStatistics;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_SUPPORTED_LIST;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.InformationBuffer = NULL;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.InformationBufferLength = 0;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.BytesWritten = 0;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
|
|
|
//
|
|
// Put request on queue
|
|
//
|
|
Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(&OpenRequest.Request);
|
|
ndisMQueueRequest(Miniport, &OpenRequest.Request, NULL);
|
|
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL, NULL);
|
|
|
|
if (LocalLock)
|
|
{
|
|
NDISM_PROCESS_DEFERRED(Miniport);
|
|
}
|
|
|
|
UNLOCK_MINIPORT(Miniport, LocalLock);
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
|
|
|
//
|
|
// The completion routine will set NdisRequestStatus.
|
|
//
|
|
WAIT_FOR_OBJECT(&OpenRequest.Event, NULL);
|
|
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
|
|
LOCK_MINIPORT(Miniport, LocalLock);
|
|
|
|
NdisStatus = OpenRequest.NdisStatus;
|
|
|
|
if ((NdisStatus != NDIS_STATUS_INVALID_LENGTH) &&
|
|
(NdisStatus != NDIS_STATUS_BUFFER_TOO_SHORT))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Now we know how much is needed, allocate temp storage...
|
|
//
|
|
TmpBufferLength = OpenRequest.Request.DATA.QUERY_INFORMATION.BytesNeeded;
|
|
TmpBuffer = ALLOC_FROM_POOL(TmpBufferLength, NDIS_TAG_DEFAULT);
|
|
|
|
if (TmpBuffer == NULL)
|
|
{
|
|
NdisStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// ...and query the real list.
|
|
//
|
|
|
|
RESET_EVENT(&OpenRequest.Event);
|
|
|
|
OpenRequest.Request.RequestType = NdisRequestQueryStatistics;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_SUPPORTED_LIST;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.InformationBuffer = TmpBuffer;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.InformationBufferLength = TmpBufferLength;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.BytesWritten = 0;
|
|
OpenRequest.Request.DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
|
|
|
//
|
|
// Put request on queue
|
|
//
|
|
|
|
Reserved = PNDIS_RESERVED_FROM_PNDIS_REQUEST(&OpenRequest.Request);
|
|
ndisMQueueRequest(Miniport, &OpenRequest.Request, NULL);
|
|
|
|
NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL, NULL);
|
|
|
|
if (LocalLock)
|
|
{
|
|
NDISM_PROCESS_DEFERRED(Miniport);
|
|
}
|
|
|
|
UNLOCK_MINIPORT(Miniport, LocalLock);
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
|
|
|
//
|
|
// The completion routine will set NdisRequestStatus.
|
|
//
|
|
|
|
WAIT_FOR_OBJECT(&OpenRequest.Event, NULL);
|
|
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
|
|
LOCK_MINIPORT(Miniport, LocalLock);
|
|
|
|
NdisStatus = OpenRequest.NdisStatus;
|
|
|
|
ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
NdisStatus = ndisSplitStatisticsOids(OpenContext,
|
|
TmpBuffer,
|
|
TmpBufferLength/sizeof(NDIS_OID));
|
|
|
|
DBGPRINT(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
|
|
("Exit query oid list\n"));
|
|
|
|
FREE_POOL(TmpBuffer);
|
|
} while (FALSE);
|
|
|
|
UNLOCK_MINIPORT(Miniport, LocalLock);
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
|
|
|
return(NdisStatus);
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMCloseAction(
|
|
IN NDIS_HANDLE MacBindingHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when a particular binding
|
|
was closed while it was indicating through NdisIndicateReceive
|
|
|
|
All this routine needs to do is to decrement the reference count
|
|
of the binding.
|
|
|
|
NOTE: This routine assumes that it is called with the lock acquired.
|
|
|
|
Arguments:
|
|
|
|
MacBindingHandle - The context value returned by the driver when the
|
|
adapter was opened. In reality, it is a pointer to W_OPEN_BLOCK.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_M_OPEN_BLOCK Open = PNDIS_M_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
|
|
PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
|
|
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("ndisMCloseAction()\n"));
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("- Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
|
|
Open->References--;
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO,
|
|
("==0 Open 0x%x Reference 0x%x\n", Open, Open->References));
|
|
|
|
if (Open->References == 0)
|
|
{
|
|
ndisMFinishClose(Miniport,Open);
|
|
}
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisMChangeFunctionalAddress(
|
|
IN TR_FUNCTIONAL_ADDRESS OldFunctionalAddress,
|
|
IN TR_FUNCTIONAL_ADDRESS NewFunctionalAddress,
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when an address is added to
|
|
the filter that wasn't referenced by any other open binding.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
OldFunctionalAddress - The previous functional address.
|
|
|
|
NewFunctionalAddress - The new functional address.
|
|
|
|
MacBindingHandle - The context value returned by the driver when the
|
|
adapter was opened. In reality, it is a pointer to W_OPEN_BLOCK.
|
|
|
|
NdisRequest - A pointer to the Request that submitted the set command.
|
|
|
|
Set - If true the change resulted from a set, otherwise the
|
|
change resulted from a open closing.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("ndisMChangeFunctionalAddress()\n"));
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisMChangeGroupAddress(
|
|
IN TR_FUNCTIONAL_ADDRESS OldGroupAddress,
|
|
IN TR_FUNCTIONAL_ADDRESS NewGroupAddress,
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when a group address is to
|
|
be changed.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
OldGroupAddress - The previous group address.
|
|
|
|
NewGroupAddress - The new group address.
|
|
|
|
MacBindingHandle - The context value returned by the driver when the
|
|
adapter was opened. In reality, it is a pointer to W_OPEN_BLOCK.
|
|
|
|
NdisRequest - A pointer to the Request that submitted the set command.
|
|
|
|
Set - If true the change resulted from a set, otherwise the
|
|
change resulted from a open closing.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("ndisMChangeGroupAddress()\n"));
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisMChangeFddiAddresses(
|
|
IN UINT oldLongAddressCount,
|
|
IN CHAR oldLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
|
|
IN UINT newLongAddressCount,
|
|
IN CHAR newLongAddresses[][FDDI_LENGTH_OF_LONG_ADDRESS],
|
|
IN UINT oldShortAddressCount,
|
|
IN CHAR oldShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
|
|
IN UINT newShortAddressCount,
|
|
IN CHAR newShortAddresses[][FDDI_LENGTH_OF_SHORT_ADDRESS],
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when the multicast address
|
|
list has changed.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
oldAddressCount - The number of addresses in oldAddresses.
|
|
|
|
oldAddresses - The old multicast address list.
|
|
|
|
newAddressCount - The number of addresses in newAddresses.
|
|
|
|
newAddresses - The new multicast address list.
|
|
|
|
macBindingHandle - The context value returned by the driver when the
|
|
adapter was opened. In reality, it is a pointer to W_OPEN_BLOCK.
|
|
|
|
requestHandle - A value supplied by the NDIS interface that the driver
|
|
must use when completing this request.
|
|
|
|
Set - If true the change resulted from a set, otherwise the
|
|
change resulted from a open closing.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("ndisMChangeFddiAddresses()\n"));
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisMChangeEthAddresses(
|
|
IN UINT OldAddressCount,
|
|
IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
|
|
IN UINT NewAddressCount,
|
|
IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when the multicast address
|
|
list has changed.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
OldAddressCount - The number of addresses in OldAddresses.
|
|
|
|
OldAddresses - The old multicast address list.
|
|
|
|
NewAddressCount - The number of addresses in NewAddresses.
|
|
|
|
NewAddresses - The new multicast address list.
|
|
|
|
MacBindingHandle - The context value returned by the driver when the
|
|
adapter was opened. In reality, it is a pointer to W_OPEN_BLOCK.
|
|
|
|
RequestHandle - A value supplied by the NDIS interface that the driver
|
|
must use when completing this request.
|
|
|
|
Set - If true the change resulted from a set, otherwise the
|
|
change resulted from a open closing.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_M_OPEN_BLOCK Open = PNDIS_M_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
|
|
PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
|
|
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("Enter ChangeEthAddresses\n"));
|
|
|
|
if ((Miniport->MediaType == NdisMediumArcnet878_2) &&
|
|
MINIPORT_TEST_FLAG(Open, fMINIPORT_OPEN_USING_ETH_ENCAPSULATION))
|
|
{
|
|
if (NewAddressCount > 0)
|
|
{
|
|
//
|
|
// Turn on broadcast acceptance.
|
|
//
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_ARCNET_BROADCAST_SET);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unset the broadcast filter.
|
|
//
|
|
MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_ARCNET_BROADCAST_SET);
|
|
}
|
|
|
|
//
|
|
// Need to return success here so that we don't call down to the
|
|
// ARCnet miniport with an invalid OID, i.e. an ethernet one....
|
|
//
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("ndisMChangeEthAddresses()\n"));
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
ndisMChangeClass(
|
|
IN UINT OldFilterClasses,
|
|
IN UINT NewFilterClasses,
|
|
IN NDIS_HANDLE MacBindingHandle,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN BOOLEAN Set
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action routine that will get called when a particular filter
|
|
class is first used or last cleared.
|
|
|
|
NOTE: This routine assumes that it is called with the lock
|
|
acquired.
|
|
|
|
Arguments:
|
|
|
|
OldFilterClasses - The values of the class filter before it
|
|
was changed.
|
|
|
|
NewFilterClasses - The current value of the class filter
|
|
|
|
MacBindingHandle - The context value returned by the driver when the
|
|
adapter was opened. In reality, it is a pointer to W_OPEN_BLOCK.
|
|
|
|
RequestHandle - A value supplied by the NDIS interface that the driver
|
|
must use when completing this request.
|
|
|
|
Set - If true the change resulted from a set, otherwise the
|
|
change resulted from a open closing.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DBGPRINT(DBG_COMP_FILTER, DBG_LEVEL_INFO,
|
|
("ndisMChangeClass()\n"));
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|