📄 nic_req.c
字号:
/*++
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 + -