📄 miniport.c
字号:
//
(VOID)PtDeregisterDevice();
//
// Unlink the VELAN from its parent ADAPT structure. This will
// dereference the VELAN.
//
pVElan->MiniportAdapterHandle = NULL;
PtUnlinkVElanFromAdapter(pVElan);
DBGPRINT(MUX_LOUD, ("<== MiniportHalt: pVElan %p\n", pVElan));
}
NDIS_STATUS
MPForwardRequest(
IN PVELAN pVElan,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesReadOrWritten,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Utility routine that forwards an NDIS request made on a VELAN to the
lower binding. Since at most a single request can be pended on a VELAN,
we use the pre-allocated request structure embedded in the VELAN struct.
Arguments:
Return Value:
NDIS_STATUS_PENDING if a request was sent down.
--*/
{
NDIS_STATUS Status;
PMUX_NDIS_REQUEST pMuxNdisRequest = &pVElan->Request;
DBGPRINT(MUX_LOUD, ("MPForwardRequest: VELAN %p, OID %x\n", pVElan, Oid));
do
{
MUX_INCR_PENDING_SENDS(pVElan);
//
// If the miniport below is going away, fail the request
//
NdisAcquireSpinLock(&pVElan->Lock);
if (pVElan->DeInitializing == TRUE)
{
NdisReleaseSpinLock(&pVElan->Lock);
MUX_DECR_PENDING_SENDS(pVElan);
Status = NDIS_STATUS_FAILURE;
break;
}
NdisReleaseSpinLock(&pVElan->Lock);
//
// If the virtual miniport edge is at a low power
// state, fail this request.
//
if (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
{
MUX_DECR_PENDING_SENDS(pVElan);
Status = NDIS_STATUS_ADAPTER_NOT_READY;
break;
}
pVElan->BytesNeeded = BytesNeeded;
pVElan->BytesReadOrWritten = BytesReadOrWritten;
pMuxNdisRequest->pCallback = PtCompleteForwardedRequest;
switch (RequestType)
{
case NdisRequestQueryInformation:
pMuxNdisRequest->Request.RequestType = NdisRequestQueryInformation;
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid = Oid;
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer =
InformationBuffer;
pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
case NdisRequestSetInformation:
pMuxNdisRequest->Request.RequestType = NdisRequestSetInformation;
pMuxNdisRequest->Request.DATA.SET_INFORMATION.Oid = Oid;
pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBuffer =
InformationBuffer;
pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
default:
ASSERT(FALSE);
break;
}
//
// If the miniport below is going away
//
NdisAcquireSpinLock(&pVElan->Lock);
if (pVElan->DeInitializing == TRUE)
{
NdisReleaseSpinLock(&pVElan->Lock);
MUX_DECR_PENDING_SENDS(pVElan);
Status = NDIS_STATUS_FAILURE;
break;
}
// If the lower binding has been notified of a low
// power state, queue this request; it will be picked
// up again when the lower binding returns to D0.
//
if (MUX_IS_LOW_POWER_STATE(pVElan->pAdapt->PtDevicePowerState))
{
DBGPRINT(MUX_INFO, ("ForwardRequest: VELAN %p, Adapt %p power"
" state is %d, queueing OID %x\n",
pVElan, pVElan->pAdapt,
pVElan->pAdapt->PtDevicePowerState, Oid));
pVElan->QueuedRequest = TRUE;
NdisReleaseSpinLock(&pVElan->Lock);
Status = NDIS_STATUS_PENDING;
break;
}
NdisReleaseSpinLock(&pVElan->Lock);
NdisRequest(&Status,
pVElan->BindingHandle,
&pMuxNdisRequest->Request);
if (Status != NDIS_STATUS_PENDING)
{
PtRequestComplete(pVElan->pAdapt, &pMuxNdisRequest->Request, Status);
Status = NDIS_STATUS_PENDING;
break;
}
}
while (FALSE);
return (Status);
}
NDIS_STATUS
MPSetPacketFilter(
IN PVELAN pVElan,
IN ULONG PacketFilter
)
/*++
Routine Description:
This routine will set up the VELAN so that it accepts packets
that match the specified packet filter. The only filter bits
that can truly be toggled are for broadcast and promiscuous.
The MUX driver always sets the lower binding to promiscuous
mode, but we do some optimization here to avoid turning on
receives too soon. That is, we set the packet filter on the lower
binding to a non-zero value iff at least one of the VELANs
has a non-zero filter value.
NOTE: setting the lower binding to promiscuous mode can
impact CPU utilization. The only reason we set the lower binding
to promiscuous mode in this sample is that we need to be able
to receive unicast frames directed to MAC address(es) that do not
match the local adapter's MAC address. If VELAN MAC addresses
are set to be equal to that of the adapter below, it is sufficient
to set the lower packet filter to the bitwise OR'ed value of
packet filter settings on all VELANs.
Arguments:
pVElan - pointer to VELAN
PacketFilter - the new packet filter
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_NOT_SUPPORTED
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PADAPT pAdapt;
PVELAN pTmpVElan;
PLIST_ENTRY p;
ULONG AdapterFilter;
BOOLEAN bSendUpdate = FALSE;
LOCK_STATE LockState;
DBGPRINT(MUX_LOUD, ("=> SetPacketFilter VELAN %p, Filter %x\n", pVElan, PacketFilter));
do
{
//
// Any bits not supported?
//
if (PacketFilter & ~VELAN_SUPPORTED_FILTERS)
{
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
AdapterFilter = 0;
pAdapt = pVElan->pAdapt;
//
// Grab a Write lock on the adapter so that this operation
// does not interfere with any receives that might be accessing
// filter information.
//
MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
//
// Save the new packet filter value
//
pVElan->PacketFilter = PacketFilter;
//
// Compute the new combined filter for all VELANs on this
// adapter.
//
for (p = pAdapt->VElanList.Flink;
p != &pAdapt->VElanList;
p = p->Flink)
{
pTmpVElan = CONTAINING_RECORD(p, VELAN, Link);
AdapterFilter |= pTmpVElan->PacketFilter;
}
//
// If all VELANs have packet filters set to 0, turn off
// receives on the lower adapter, if not already done.
//
if ((AdapterFilter == 0) && (pAdapt->PacketFilter != 0))
{
bSendUpdate = TRUE;
pAdapt->PacketFilter = 0;
}
else
//
// If receives had been turned off on the lower adapter, and
// the new filter is non-zero, turn on the lower adapter.
// We set the adapter to promiscuous mode in this sample
// so that we are able to receive packets directed to
// any of the VELAN MAC addresses.
//
if ((AdapterFilter != 0) && (pAdapt->PacketFilter == 0))
{
bSendUpdate = TRUE;
pAdapt->PacketFilter = MUX_ADAPTER_PACKET_FILTER;
}
MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
if (bSendUpdate)
{
PtRequestAdapterAsync(
pAdapt,
NdisRequestSetInformation,
OID_GEN_CURRENT_PACKET_FILTER,
&pAdapt->PacketFilter,
sizeof(pAdapt->PacketFilter),
PtDiscardCompletedRequest);
}
}
while (FALSE);
DBGPRINT(MUX_INFO, ("<= SetPacketFilter VELAN %p, Status %x\n", pVElan, Status));
return(Status);
}
NDIS_STATUS
MPSetMulticastList(
IN PVELAN pVElan,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG pBytesRead,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Set the multicast list on the specified VELAN miniport.
We simply validate all information and copy in the multicast
list.
We don't forward the multicast list information down since
we set the lower binding to promisc. mode.
Arguments:
pVElan - VELAN on which to set the multicast list
InformationBuffer - pointer to new multicast list
InformationBufferLength - length in bytes of above list
pBytesRead - place to return # of bytes read from the above
pBytesNeeded - place to return expected min # of bytes
Return Value:
NDIS_STATUS
--*/
{
NDIS_STATUS Status;
PADAPT pAdapt;
LOCK_STATE LockState;
//
// Initialize.
//
*pBytesNeeded = sizeof(MUX_MAC_ADDRESS);
*pBytesRead = 0;
Status = NDIS_STATUS_SUCCESS;
do
{
if (InformationBufferLength % sizeof(MUX_MAC_ADDRESS))
{
Status = NDIS_STATUS_INVALID_LENGTH;
break;
}
if (InformationBufferLength > (VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS)))
{
Status = NDIS_STATUS_MULTICAST_FULL;
*pBytesNeeded = VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS);
break;
}
pAdapt = pVElan->pAdapt;
//
// Grab a Write lock on the adapter so that this operation
// does not interfere with any receives that might be accessing
// multicast list information.
//
MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
NdisZeroMemory(&pVElan->McastAddrs[0],
VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS));
NdisMoveMemory(&pVElan->McastAddrs[0],
InformationBuffer,
InformationBufferLength);
pVElan->McastAddrCount = InformationBufferLength / sizeof(MUX_MAC_ADDRESS);
MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
}
while (FALSE);
return (Status);
}
//
// Careful! Uses static storage for string. Used to simplify DbgPrints
// of MAC addresses.
//
PUCHAR
MacAddrToString(PVOID In)
{
static UCHAR String[20];
static PCHAR HexChars = "0123456789abcdef";
PUCHAR EthAddr = (PUCHAR) In;
UINT i;
PUCHAR s;
for (i = 0, s = String; i < 6; i++, EthAddr++)
{
*s++ = HexChars[(*EthAddr) >> 4];
*s++ = HexChars[(*EthAddr) & 0xf];
}
*s = '\0';
return String;
}
VOID
MPGenerateMacAddr(
PVELAN pVElan
)
/*++
Routine Description:
Generates a "virtual" MAC address for a VELAN.
NOTE: this is only a sample implementation of selecting
a MAC address for the VELAN. Other implementations are possible,
including using the MAC address of the underlying adapter as
the MAC address of the VELAN.
Arguments:
pVElan - Pointer to velan structure
Return Value:
None
--*/
{
pVElan->PermanentAddress[0] =
0x02 | (((UCHAR)pVElan->VElanNumber & 0x3f) << 2);
pVElan->PermanentAddress[1] =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -