windows-nt/Source/XPSP1/NT/net/ndis/tunmp/sys/request.c
2020-09-26 16:20:57 +08:00

536 lines
15 KiB
C

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
send.c
Abstract:
NDIS entry points to handle requests.
Environment:
Kernel mode only.
Revision History:
alid 10/22/2001 modified for tunmp
arvindm 4/10/2000 Created
--*/
#include "precomp.h"
#define __FILENUMBER 'TQER'
NDIS_OID TunMpSupportedOidArray[] =
{
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_MAC_OPTIONS,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_RECEIVE_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_CURRENT_LOOKAHEAD,
OID_GEN_DRIVER_VERSION,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_MAXIMUM_SEND_PACKETS,
OID_PNP_CAPABILITIES,
OID_PNP_SET_POWER,
OID_PNP_QUERY_POWER,
OID_GEN_XMIT_OK,
OID_GEN_RCV_OK,
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER,
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_802_3_MULTICAST_LIST,
OID_802_3_MAXIMUM_LIST_SIZE,
OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION,
OID_802_3_XMIT_MORE_COLLISIONS,
OID_CUSTOM_TUNMP_INSTANCE_ID
};
UINT TunMpSupportedOids = sizeof(TunMpSupportedOidArray)/sizeof(NDIS_OID);
UCHAR TunMpVendorDescription[] = "MS Tunnel Interface Driver";
UCHAR TunMpVendorId[3] = {0xFF, 0xFF, 0xFF};
NDIS_PNP_CAPABILITIES Power_Management_Capabilities = { 0,
NdisDeviceStateUnspecified,
NdisDeviceStateUnspecified,
NdisDeviceStateUnspecified
};
NDIS_STATUS
TunMpQueryInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Miniport QueryInfo handler.
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesWritten Specifies how much info is written
BytesNeeded In case the buffer is smaller than what
we need, tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PTUN_ADAPTER pAdapter = (PTUN_ADAPTER)MiniportAdapterContext;
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
UINT i;
NDIS_OID MaskOid;
PVOID SourceBuffer;
UINT SourceBufferLength;
ULONG GenericUlong = 0;
USHORT GenericUshort;
DEBUGP(DL_LOUD, ("==>TunMpQueryInformation: Adapter %p, Oid %lx\n",
pAdapter, Oid));
*BytesWritten = 0;
*BytesNeeded = 0;
//
// Initialize these once, since this is the majority of cases.
//
SourceBuffer = (PVOID)&GenericUlong;
SourceBufferLength = sizeof(ULONG);
switch (Oid)
{
case OID_GEN_MAC_OPTIONS:
GenericUlong = (ULONG)(NDIS_MAC_OPTION_NO_LOOPBACK);
break;
case OID_GEN_SUPPORTED_LIST:
(NDIS_OID*)SourceBuffer = TunMpSupportedOidArray;
SourceBufferLength = TunMpSupportedOids * sizeof(ULONG);
break;
case OID_GEN_HARDWARE_STATUS:
GenericUlong = NdisHardwareStatusReady;
break;
case OID_GEN_MEDIA_SUPPORTED:
case OID_GEN_MEDIA_IN_USE:
GenericUlong = pAdapter->Medium;
break;
case OID_GEN_MAXIMUM_LOOKAHEAD:
GenericUlong = pAdapter->MaxLookAhead;
break;
case OID_GEN_MAXIMUM_FRAME_SIZE:
GenericUlong = pAdapter->MediumMaxFrameLen;
break;
case OID_GEN_LINK_SPEED:
GenericUlong = pAdapter->MediumLinkSpeed;
break;
case OID_GEN_TRANSMIT_BUFFER_SPACE:
GenericUlong = (pAdapter->MediumMaxPacketLen);
break;
case OID_GEN_RECEIVE_BUFFER_SPACE:
GenericUlong = (pAdapter->MediumMaxPacketLen);
break;
case OID_GEN_TRANSMIT_BLOCK_SIZE:
GenericUlong = 1;
break;
case OID_GEN_RECEIVE_BLOCK_SIZE:
GenericUlong = 1;
break;
case OID_GEN_VENDOR_ID:
SourceBuffer = TunMpVendorId;
SourceBufferLength = sizeof(TunMpVendorId);
break;
case OID_GEN_VENDOR_DESCRIPTION:
SourceBuffer = TunMpVendorDescription;
SourceBufferLength = sizeof(TunMpVendorDescription);
break;
case OID_GEN_CURRENT_PACKET_FILTER:
GenericUlong = pAdapter->PacketFilter;
break;
case OID_GEN_CURRENT_LOOKAHEAD:
GenericUlong = pAdapter->MaxLookAhead;
break;
case OID_GEN_DRIVER_VERSION:
GenericUshort = (NDIS_MINIPORT_MAJOR_VERSION << 8) + NDIS_MINIPORT_MINOR_VERSION;
SourceBuffer = &GenericUshort;
SourceBufferLength = sizeof(USHORT);
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
GenericUlong = pAdapter->MediumMaxPacketLen;
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
KdPrint(("OID_GEN_MEDIA_CONNECT_STATUS: %lx\n", Oid));
if(TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OPEN))
GenericUlong = NdisMediaStateConnected;
else
GenericUlong = NdisMediaStateDisconnected;
break;
case OID_GEN_MAXIMUM_SEND_PACKETS:
GenericUlong = MAX_RECV_QUEUE_SIZE;
break;
case OID_GEN_XMIT_OK:
SourceBuffer = &(pAdapter->SendPackets);
SourceBufferLength = sizeof(ULONG);
break;
case OID_GEN_RCV_OK:
SourceBuffer = &(pAdapter->RcvPackets);
SourceBufferLength = sizeof(ULONG);
break;
case OID_GEN_XMIT_ERROR:
SourceBuffer = &(pAdapter->XmitError);
SourceBufferLength = sizeof(ULONG);
break;
case OID_GEN_RCV_ERROR:
SourceBuffer = &(pAdapter->RcvError);
SourceBufferLength = sizeof(ULONG);
break;
case OID_GEN_RCV_NO_BUFFER:
SourceBuffer = &(pAdapter->RcvNoBuffer);
SourceBufferLength = sizeof(ULONG);
break;
case OID_802_3_PERMANENT_ADDRESS:
SourceBuffer = pAdapter->PermanentAddress;
SourceBufferLength = TUN_MAC_ADDR_LEN;
break;
case OID_802_3_CURRENT_ADDRESS:
SourceBuffer = pAdapter->CurrentAddress;
SourceBufferLength = TUN_MAC_ADDR_LEN;
break;
case OID_802_3_MAXIMUM_LIST_SIZE:
GenericUlong = TUN_MAX_MULTICAST_ADDRESS;
break;
case OID_802_3_RCV_ERROR_ALIGNMENT:
case OID_802_3_XMIT_ONE_COLLISION:
case OID_802_3_XMIT_MORE_COLLISIONS:
GenericUlong = 0;
break;
case OID_PNP_CAPABILITIES:
//
// we support going to D3, but we don't do any WOL
//
SourceBufferLength = sizeof (NDIS_PNP_CAPABILITIES);
SourceBuffer = (PVOID)&Power_Management_Capabilities;
break;
case OID_PNP_QUERY_POWER:
//
// we should always succeed this OID.
//
SourceBufferLength = 0;
break;
case OID_CUSTOM_TUNMP_INSTANCE_ID:
GenericUlong = pAdapter->DeviceInstanceNumber;
break;
default:
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
break;
}
if (NdisStatus == NDIS_STATUS_SUCCESS)
{
*BytesNeeded = SourceBufferLength;
if (SourceBufferLength <= InformationBufferLength)
{
*BytesWritten = SourceBufferLength;
if (SourceBufferLength)
{
NdisMoveMemory(InformationBuffer, SourceBuffer, SourceBufferLength);
}
}
else
{
NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
}
}
DEBUGP(DL_LOUD, ("<==TunMpQueryInformation: Adapter %p, NdisStatus %lx\n",
pAdapter, NdisStatus));
return (NdisStatus);
}
NDIS_STATUS
TunMpSetInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Miniport SetInfo handler.
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesRead Specifies how much info is read
BytesNeeded In case the buffer is smaller than what we need,
tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PTUN_ADAPTER pAdapter = (PTUN_ADAPTER)MiniportAdapterContext;
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
NDIS_DEVICE_POWER_STATE NewPowerState;
DEBUGP(DL_LOUD, ("==>TunMpSetInformation: Adapter %p, Oid %lx\n",
pAdapter, Oid));
*BytesRead = 0;
*BytesNeeded = 0;
switch (Oid)
{
case OID_GEN_CURRENT_PACKET_FILTER:
if (InformationBufferLength != sizeof(ULONG))
{
NdisStatus = NDIS_STATUS_INVALID_DATA;
}
else
{
ULONG PacketFilter;
PacketFilter = *(UNALIGNED ULONG *)InformationBuffer;
pAdapter->PacketFilter = PacketFilter;
*BytesRead = InformationBufferLength;
TUN_ACQUIRE_LOCK(&pAdapter->Lock);
if (PacketFilter != 0)
{
//
// if packet filter is set to a non-zero value, then activate
// the adapter. i.e. start indicating packets.
//
TUN_SET_FLAG(pAdapter, TUN_ADAPTER_ACTIVE);
}
else
{
//
// if packet filter is set to zero, then we should
// fail all writes
//
TUN_CLEAR_FLAG(pAdapter, TUN_ADAPTER_ACTIVE);
if (pAdapter->PendedSendCount != 0)
{
NdisStatus = NDIS_STATUS_PENDING;
TUN_SET_FLAG(pAdapter, TUN_COMPLETE_REQUEST);
}
else
{
NdisStatus = NDIS_STATUS_SUCCESS;
}
}
TUN_RELEASE_LOCK(&pAdapter->Lock);
}
break;
case OID_GEN_CURRENT_LOOKAHEAD:
if (InformationBufferLength != sizeof(ULONG))
{
NdisStatus = NDIS_STATUS_INVALID_DATA;
}
else
{
ULONG CurrentLookahead;
CurrentLookahead = *(UNALIGNED ULONG *)InformationBuffer;
if (CurrentLookahead > TUN_MAX_LOOKAHEAD)
{
NdisStatus = NDIS_STATUS_INVALID_LENGTH;
}
else if (CurrentLookahead >= pAdapter->MaxLookAhead)
{
pAdapter->MaxLookAhead = CurrentLookahead;
*BytesRead = sizeof(ULONG);
NdisStatus = NDIS_STATUS_SUCCESS;
}
}
break;
case OID_802_3_MULTICAST_LIST:
if (pAdapter->Medium != NdisMedium802_3)
{
NdisStatus = NDIS_STATUS_INVALID_OID;
break;
}
if ((InformationBufferLength % ETH_LENGTH_OF_ADDRESS) != 0)
{
NdisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
//1 set BytesNeeded, check for max multicastlist
break;
case OID_PNP_SET_POWER:
if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
{
NdisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
NewPowerState = *(PNDIS_DEVICE_POWER_STATE)InformationBuffer;
*BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
TUN_ACQUIRE_LOCK(&pAdapter->Lock);
if (NewPowerState != NdisDeviceStateD0)
{
//
// complete any oustanding NDIS sends. do not allow any
// more NDIS sends. wait for all the indicated packets
// to return and do not allow any more packet
// indications (application Write)
//
TUN_CLEAR_FLAG(pAdapter, TUN_ADAPTER_ACTIVE);
TUN_SET_FLAG(pAdapter, TUN_ADAPTER_OFF);
//
// complete all outstanding NDIS Send requests
//
TUN_RELEASE_LOCK(&pAdapter->Lock);
//
// abort all pending NDIS send requests
TunFlushReceiveQueue(pAdapter);
//
// cancel all pending read IRPs if any
//
TunCancelPendingReads(pAdapter);
TUN_ACQUIRE_LOCK(&pAdapter->Lock);
//
// is there any outstanding NDIS sends?
//
if ((pAdapter->PendedSendCount != 0) ||
(pAdapter->PendedReadCount != 0))
{
NdisStatus = NDIS_STATUS_PENDING;
TUN_SET_FLAG(pAdapter, TUN_COMPLETE_REQUEST);
}
}
else
{
TUN_CLEAR_FLAG(pAdapter, TUN_ADAPTER_OFF);
if (pAdapter->PacketFilter != 0)
{
TUN_SET_FLAG(pAdapter, TUN_ADAPTER_ACTIVE);
}
//
//
NdisStatus = NDIS_STATUS_SUCCESS;
}
TUN_RELEASE_LOCK(&pAdapter->Lock);
break;
default:
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
break;
}
DEBUGP(DL_LOUD, ("<==TunMpSetInformation: Adapter %p, NdisStatus %lx\n",
pAdapter, NdisStatus));
return NdisStatus;
}