Windows NT 4.0 source code leak
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

/*++
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);
}