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

📄 nic_req.c

📁 ddk开发pci范例,使用9054芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:
    mp_req.c

Abstract:
    This module handle NDIS OID ioctls. This module is not required
    if the upper edge is not NDIS.


Environment:

    Kernel mode


Revision History:
    DChen       11-01-99    created
    EliyasY     Feb 13, 2003 converted to WDM
    
--*/

#include "precomp.h"

#if defined(EVENT_TRACING)
#include "nic_req.tmh"
#endif

//
// Following status values are copied from NDIS.H
//
#define NDIS_STATUS_MEDIA_CONNECT       0x4001000BL
#define NDIS_STATUS_MEDIA_DISCONNECT    0x4001000CL

NTSTATUS
PciDrvPowerBeginQueuingIrps(
    IN  PDEVICE_OBJECT      DeviceObject,
    IN  ULONG               IrpIoCharges,
    IN  BOOLEAN             Query
    );

NTSTATUS
NICHandleQueryOidRequest(
    IN  PFDO_DATA                   FdoData,
    IN  PIRP                        Irp,
    OUT PULONG                      BytesWritten
    )
/*++

Routine Description:

    Query an arbitrary OID value from the miniport.

Arguments:

    FdoData - pointer to open context representing our binding to the miniport
    DataBuffer - place to store the returned value
    BufferLength - length of the above
    BytesWritten - place to return length returned

Return Value:


--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    PNDISPROT_QUERY_OID     pQuery;
    NDIS_OID                Oid;
    ULONG                   ulInfo = 0;
    ULONG64                 ul64Info = 0;    
    PVOID                   pInfo = (PVOID) &ulInfo;
    ULONG                   ulInfoLen = sizeof(ulInfo);
    PVOID                   InformationBuffer = NULL;
    ULONG                   InformationBufferLength = 0;
    MEDIA_STATE             CurrMediaState;
    ULONG                   ulBytesAvailable = ulInfoLen;
    PVOID                   DataBuffer;    
    ULONG                   BufferLength;
    PIO_STACK_LOCATION      pIrpSp;
    KIRQL                   oldIrql;
    NDIS_PNP_CAPABILITIES   Power_Management_Capabilities;
    
    pIrpSp = IoGetCurrentIrpStackLocation(Irp);
    DataBuffer = Irp->AssociatedIrp.SystemBuffer;
    BufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;   
    
    DebugPrint(TRACE, DBG_IOCTLS, "--> HandleQueryOIDRequest\n");
    Oid = 0;

    do
    {
        if (BufferLength < sizeof(NDISPROT_QUERY_OID))
        {
            status = STATUS_BUFFER_OVERFLOW;
            break;
        }

        pQuery = (PNDISPROT_QUERY_OID)DataBuffer;
        Oid = pQuery->Oid;
        InformationBuffer = &pQuery->Data[0];
        InformationBufferLength = BufferLength - 
                            FIELD_OFFSET(NDISPROT_QUERY_OID, Data);
        
        switch(Oid)
        {

        case OID_GEN_LINK_SPEED:
        case OID_GEN_MEDIA_CONNECT_STATUS:
            
            if (InformationBufferLength < ulInfoLen)
            {
                break;
            }
            
            KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
            if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION))
            {
                //
                // The device is busy doing link detection. Let us queue
                // the IRP. When the link detection is over, the watchdog
                // timer DPC will complete this IRP.
                //
                ASSERT(!FdoData->QueryRequest);
                status = PciDrvQueueIoctlIrp(FdoData, Irp);
                KeReleaseSpinLock(&FdoData->Lock, oldIrql);
                break;
            }
            else
            {            
                KeReleaseSpinLock(&FdoData->Lock, oldIrql); 
                if (Oid == OID_GEN_LINK_SPEED)
                {
                    ulInfo = FdoData->usLinkSpeed * 10000;
                } else {
             
                    CurrMediaState = NICIndicateMediaState(FdoData);            
                    ulInfo = CurrMediaState;            
                }
            }
            break;

        case OID_802_3_PERMANENT_ADDRESS:
            pInfo = FdoData->PermanentAddress;
            ulBytesAvailable = ulInfoLen = ETH_LENGTH_OF_ADDRESS;
            break;

        case OID_802_3_CURRENT_ADDRESS:
            pInfo = FdoData->CurrentAddress;
            ulBytesAvailable = ulInfoLen = ETH_LENGTH_OF_ADDRESS;
            break;

        case OID_802_3_MAXIMUM_LIST_SIZE:
            ulInfo = NIC_MAX_MCAST_LIST;
            break;
            
        case OID_GEN_XMIT_OK:
        case OID_GEN_RCV_OK:
        case OID_GEN_XMIT_ERROR:
        case OID_GEN_RCV_ERROR:
        case OID_GEN_RCV_NO_BUFFER:
        case OID_GEN_RCV_CRC_ERROR:
        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
        case OID_802_3_RCV_ERROR_ALIGNMENT:
        case OID_802_3_XMIT_ONE_COLLISION:
        case OID_802_3_XMIT_MORE_COLLISIONS:
        case OID_802_3_XMIT_DEFERRED:
        case OID_802_3_XMIT_MAX_COLLISIONS:
        case OID_802_3_RCV_OVERRUN:
        case OID_802_3_XMIT_UNDERRUN:
        case OID_802_3_XMIT_HEARTBEAT_FAILURE:
        case OID_802_3_XMIT_TIMES_CRS_LOST:
        case OID_802_3_XMIT_LATE_COLLISIONS:
            
            status = NICGetStatsCounters(FdoData, Oid, &ul64Info);
            ulBytesAvailable = ulInfoLen = sizeof(ul64Info);
            
            if (status == STATUS_SUCCESS)
            {
                if (InformationBufferLength < sizeof(ULONG))
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                    *BytesWritten = ulBytesAvailable;
                    break;
                }

                ulInfoLen = MIN(InformationBufferLength, ulBytesAvailable);
                pInfo = &ul64Info;
            }
                    
            break;         

        case OID_PNP_CAPABILITIES:

            NICFillPoMgmtCaps (FdoData, 
                                &Power_Management_Capabilities, 
                                &status,
                                &ulInfoLen);
            if (status == STATUS_SUCCESS)
            {
                pInfo = (PVOID) &Power_Management_Capabilities;
            }
            else
            {
                pInfo = NULL;
            }

            break;

        case OID_PNP_QUERY_POWER:
            // status is pre-set in this routine to Success

            status = STATUS_SUCCESS; 

            break;
            
        default:
            status = STATUS_NOT_SUPPORTED;
            break;
        }
    }while (FALSE);

    if (status == STATUS_SUCCESS)
    {
        if (ulInfoLen <= InformationBufferLength)
        {
            //
            // Copy result into InformationBuffer
            //
            *BytesWritten = ulInfoLen;
            if (ulInfoLen)
            {
                RtlMoveMemory(InformationBuffer, pInfo, ulInfoLen);
            }
        }
        else
        {
            //
            // too short
            //
            *BytesWritten = ulInfoLen;
            status = STATUS_BUFFER_TOO_SMALL;
        }
    }
    
    DebugPrint(LOUD, DBG_IOCTLS, "<--HandleQueryOIDRequest: OID %x, Status %x\n",
                Oid, status);

    return (status);
    
}

NTSTATUS
NICHandleSetOidRequest(
    IN  PFDO_DATA                   FdoData,
    IN  PIRP                       Irp
    )
/*++

Routine Description:

    This routine handles ioctl request for Set OIDs. Most of
    the IOCTL requests are only if the upper edge is NDIS.

Arguments:


Return Value:


--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    PNDISPROT_SET_OID       pSet;
    NDIS_OID                Oid;
    ULONG                   PacketFilter;
    PVOID                   InformationBuffer = NULL;
    ULONG                   InformationBufferLength = 0;
    KIRQL                   oldIrql;
    PVOID                   DataBuffer;    
    ULONG                   BufferLength, unUsed;
    PIO_STACK_LOCATION      pIrpSp;
    DEVICE_POWER_STATE      newDeviceState, oldDeviceState;
    
    pIrpSp = IoGetCurrentIrpStackLocation(Irp);
    DataBuffer = Irp->AssociatedIrp.SystemBuffer;
    BufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;   
 
    DebugPrint(LOUD, DBG_IOCTLS, "--> HandleSetOIDRequest\n");
    
    Oid = 0;

    do
    {
        if (BufferLength < sizeof(NDISPROT_SET_OID))
        {
            status = STATUS_BUFFER_OVERFLOW;
            break;
        }

        pSet = (PNDISPROT_SET_OID)DataBuffer;
        Oid = pSet->Oid;
        InformationBuffer = &pSet->Data[0];
        InformationBufferLength = BufferLength - FIELD_OFFSET(NDISPROT_SET_OID, Data);
        switch(Oid)
        {

        case OID_802_3_MULTICAST_LIST:
            //
            // Verify the length
            //
            if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0)
            {
                return(STATUS_INVALID_BUFFER_SIZE);
            }

            //
            // Save the number of MC list size
            //
            FdoData->MCAddressCount = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
            ASSERT(FdoData->MCAddressCount <= NIC_MAX_MCAST_LIST);

            //
            // Save the MC list
            //
            RtlMoveMemory(
                FdoData->MCList, 
                InformationBuffer, 
                InformationBufferLength);

            KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
            KeAcquireSpinLockAtDpcLevel(&FdoData->RcvLock);
            
            status = NICSetMulticastList(FdoData);

            KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
            KeReleaseSpinLock(&FdoData->Lock, oldIrql);
            break;

        case OID_GEN_CURRENT_PACKET_FILTER:
            //
            // Verify the Length
            //
            if (InformationBufferLength != sizeof(ULONG))
            {
                return(STATUS_INVALID_BUFFER_SIZE);
            }
            
            RtlMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG));

            //
            // any bits not supported?
            //
            if (PacketFilter & ~NIC_SUPPORTED_FILTERS)
            {
                return(STATUS_NOT_SUPPORTED);
            }

            //
            // any filtering changes?
            //
            if (PacketFilter == FdoData->PacketFilter)
            {
                break;
            }

            KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
            KeAcquireSpinLockAtDpcLevel(&FdoData->RcvLock);
            
            if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION))
            {
            
                //
                // The device is busy doing link detection. Let us queue
                // the IRP. When the link detection is over, the watchdog
                // timer DPC will complete this IRP.
                //
                ASSERT(!FdoData->SetRequest);
                status = PciDrvQueueIoctlIrp(FdoData, Irp);

                KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
                KeReleaseSpinLock(&FdoData->Lock, oldIrql);
                break;
            }

            status = NICSetPacketFilter(
                         FdoData,
                         PacketFilter);

            KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
            KeReleaseSpinLock(&FdoData->Lock, oldIrql);
            
            if (status == STATUS_SUCCESS)
            {
                FdoData->PacketFilter = PacketFilter;
            }

            break;

        case OID_PNP_SET_POWER:

            if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
            {
                return(STATUS_BUFFER_TOO_SMALL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -