⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniport.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
    //
    (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 + -