You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2038 lines
89 KiB
2038 lines
89 KiB
/***************************************************************************
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
REQUEST.C
|
|
|
|
Abstract:
|
|
|
|
Handles set and query requests
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
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.
|
|
|
|
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
|
|
|
|
|
|
Revision History:
|
|
|
|
5/13/99 : created
|
|
|
|
Author:
|
|
|
|
Tom Green
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
#ifdef TESTING
|
|
extern PUCHAR pOffloadBuffer;
|
|
extern ULONG OffloadSize;
|
|
#endif
|
|
|
|
// supported OID list
|
|
NDIS_OID RndismpSupportedOids[] =
|
|
{
|
|
OID_GEN_SUPPORTED_LIST,
|
|
OID_GEN_MEDIA_IN_USE,
|
|
OID_GEN_MAXIMUM_LOOKAHEAD,
|
|
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
|
OID_GEN_PROTOCOL_OPTIONS,
|
|
OID_GEN_TRANSMIT_BUFFER_SPACE,
|
|
OID_GEN_RECEIVE_BUFFER_SPACE,
|
|
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
|
OID_GEN_RECEIVE_BLOCK_SIZE,
|
|
OID_GEN_VENDOR_DESCRIPTION,
|
|
OID_GEN_DRIVER_VERSION,
|
|
OID_GEN_VENDOR_ID,
|
|
OID_GEN_VENDOR_DRIVER_VERSION,
|
|
OID_GEN_CURRENT_LOOKAHEAD,
|
|
OID_GEN_MAXIMUM_SEND_PACKETS,
|
|
OID_GEN_XMIT_OK,
|
|
OID_GEN_RCV_OK,
|
|
OID_GEN_XMIT_ERROR,
|
|
OID_GEN_RCV_ERROR,
|
|
OID_GEN_RCV_NO_BUFFER,
|
|
OID_GEN_MAC_OPTIONS,
|
|
OID_RNDISMP_STATISTICS,
|
|
#ifdef TESTING
|
|
OID_TCP_TASK_OFFLOAD,
|
|
OID_GEN_TRANSPORT_HEADER_OFFSET,
|
|
OID_GEN_PHYSICAL_MEDIUM,
|
|
#endif
|
|
OID_GEN_SUPPORTED_GUIDS
|
|
};
|
|
|
|
UINT RndismpSupportedOidsNum = sizeof(RndismpSupportedOids) / sizeof(NDIS_OID);
|
|
|
|
#ifdef BINARY_MOF_TEST
|
|
|
|
UCHAR RndismpBinaryMof[] = {
|
|
0x46, 0x4f, 0x4d, 0x42, 0x01, 0x00, 0x00, 0x00, 0x45, 0x02, 0x00, 0x00, 0xbc, 0x04, 0x00, 0x00,
|
|
0x44, 0x53, 0x00, 0x01, 0x1a, 0x7d, 0xda, 0x54, 0x18, 0x44, 0x82, 0x00, 0x01, 0x06, 0x18, 0x42,
|
|
0x20, 0xe4, 0x03, 0x89, 0xc0, 0x61, 0x68, 0x24, 0x18, 0x06, 0xe5, 0x01, 0x44, 0x6a, 0x20, 0xe4,
|
|
0x82, 0x89, 0x09, 0x10, 0x01, 0x21, 0xaf, 0x02, 0x6c, 0x0a, 0x30, 0x09, 0xa2, 0xfe, 0xfd, 0x15,
|
|
0xa1, 0xa1, 0x84, 0x40, 0x48, 0xa2, 0x00, 0xf3, 0x02, 0x74, 0x0b, 0x30, 0x2c, 0xc0, 0xb6, 0x00,
|
|
0xd3, 0x02, 0x1c, 0x23, 0x12, 0x65, 0xd0, 0x94, 0xc0, 0x4a, 0x20, 0x24, 0x54, 0x80, 0x72, 0x01,
|
|
0xbe, 0x05, 0x68, 0x07, 0x94, 0x64, 0x01, 0x96, 0x61, 0x34, 0x07, 0x0e, 0xc6, 0x09, 0x8a, 0x46,
|
|
0x46, 0xa9, 0x80, 0x90, 0x67, 0x01, 0xd6, 0x71, 0x09, 0x41, 0xf7, 0x02, 0xa4, 0x09, 0x70, 0x26,
|
|
0xc0, 0xdb, 0x34, 0xa4, 0x59, 0xc0, 0x30, 0x22, 0xd8, 0x16, 0x8e, 0x30, 0xe2, 0x9c, 0x42, 0x94,
|
|
0xc6, 0x10, 0x84, 0x19, 0x31, 0x4a, 0x73, 0x58, 0x82, 0x8a, 0x11, 0xa5, 0x30, 0x04, 0x01, 0x86,
|
|
0x88, 0x55, 0x9c, 0x00, 0x6b, 0x58, 0x42, 0x39, 0x80, 0x13, 0xb0, 0xfd, 0x39, 0x48, 0x13, 0x84,
|
|
0x1c, 0x4c, 0x0b, 0x25, 0x7b, 0x40, 0x9a, 0xc6, 0xf1, 0x05, 0x39, 0x87, 0x83, 0x61, 0x26, 0x86,
|
|
0x2c, 0x55, 0x98, 0x28, 0x2d, 0x73, 0x23, 0xe3, 0xb4, 0x45, 0x01, 0xe2, 0x05, 0x08, 0x07, 0xd5,
|
|
0x58, 0x3b, 0xc7, 0xd0, 0x05, 0x80, 0xa9, 0x1e, 0x1e, 0x4a, 0xcc, 0x98, 0x09, 0x5a, 0xbc, 0x93,
|
|
0x38, 0xcc, 0xc0, 0x61, 0x4b, 0xc7, 0xd0, 0x40, 0x02, 0x27, 0x68, 0x10, 0x49, 0x8a, 0x71, 0x84,
|
|
0x14, 0xe4, 0x5c, 0x42, 0x9c, 0x7c, 0x41, 0x02, 0x94, 0x0a, 0xd0, 0x09, 0xac, 0x19, 0x77, 0x3a,
|
|
0x66, 0x4d, 0x39, 0x50, 0x78, 0x8f, 0xdc, 0xf8, 0x41, 0xe2, 0xf4, 0x09, 0xac, 0x79, 0x44, 0x89,
|
|
0x13, 0xba, 0xa9, 0x09, 0x28, 0xa4, 0x02, 0x88, 0x16, 0x40, 0x94, 0x66, 0x32, 0xa8, 0xab, 0x40,
|
|
0x82, 0x47, 0x03, 0x8f, 0xe0, 0xa8, 0x0c, 0x7a, 0x1a, 0x41, 0xe2, 0x7b, 0x18, 0xef, 0x04, 0x1e,
|
|
0x99, 0x87, 0x79, 0x8a, 0x0c, 0xf3, 0xff, 0xff, 0x8e, 0x80, 0x75, 0x8d, 0xa7, 0x11, 0x9d, 0x80,
|
|
0xe5, 0xa0, 0xa1, 0xae, 0x03, 0x1e, 0x57, 0xb4, 0xf8, 0xa7, 0x6c, 0xb8, 0xba, 0xc6, 0x82, 0xba,
|
|
0x2a, 0xd8, 0xe1, 0x54, 0x34, 0xb6, 0x52, 0x05, 0x98, 0x1d, 0x9c, 0xe6, 0x9c, 0xe0, 0x68, 0x3c,
|
|
0x55, 0xcf, 0xe6, 0xe1, 0x20, 0xc1, 0x23, 0x82, 0xa7, 0xc0, 0xa7, 0x65, 0x1d, 0xc3, 0x25, 0x03,
|
|
0x34, 0x62, 0xb8, 0x73, 0x32, 0x7a, 0x82, 0x3b, 0x94, 0x80, 0xd1, 0xc0, 0xbd, 0x1b, 0x1c, 0x0d,
|
|
0xec, 0x59, 0xbf, 0x04, 0x44, 0x78, 0x38, 0xf0, 0x5c, 0x3d, 0x06, 0xfd, 0x08, 0xe4, 0x64, 0x36,
|
|
0x28, 0x3d, 0x37, 0x02, 0x7a, 0x05, 0xe0, 0x27, 0x09, 0x76, 0x3c, 0x30, 0xc8, 0x29, 0x1d, 0xad,
|
|
0x53, 0x43, 0xe8, 0xad, 0xe1, 0x19, 0xc1, 0x05, 0x7e, 0x4c, 0x00, 0xcb, 0xe9, 0x00, 0x3b, 0x16,
|
|
0x3c, 0x52, 0xe3, 0x47, 0x0c, 0xe1, 0x18, 0x31, 0xc6, 0x69, 0x04, 0x0a, 0xeb, 0x91, 0x04, 0xa9,
|
|
0x70, 0xf6, 0x64, 0x98, 0x6f, 0x0a, 0x35, 0x0a, 0xb8, 0x09, 0x58, 0xd4, 0x65, 0x02, 0x25, 0xe5,
|
|
0x32, 0x81, 0x98, 0x47, 0xd8, 0xb7, 0x04, 0x4f, 0xf8, 0xac, 0x7c, 0x98, 0xf0, 0xa5, 0x00, 0xfe,
|
|
0xed, 0xc3, 0xc3, 0x08, 0xfd, 0xb0, 0xf1, 0x44, 0xe2, 0x23, 0x43, 0x5c, 0xcc, 0xff, 0x1f, 0xd7,
|
|
0x03, 0xb7, 0x5f, 0x01, 0x08, 0xb1, 0xcb, 0xbc, 0x16, 0xe8, 0x38, 0x11, 0x21, 0xc1, 0x1b, 0x05,
|
|
0x16, 0xe3, 0x60, 0x3c, 0x50, 0x9f, 0x13, 0x3c, 0x4c, 0x83, 0x1c, 0x59, 0xbc, 0x88, 0x09, 0x4e,
|
|
0xed, 0xa8, 0xb1, 0x73, 0xe0, 0x03, 0x38, 0x86, 0xf0, 0xe7, 0x13, 0xfe, 0x00, 0xa2, 0x1c, 0xc7,
|
|
0x21, 0x79, 0xc8, 0x46, 0x38, 0x81, 0x72, 0x2f, 0x2b, 0xe4, 0x58, 0x72, 0x14, 0xa7, 0xf5, 0x74,
|
|
0x10, 0xe8, 0x04, 0x30, 0x0a, 0x6d, 0xfa, 0xd4, 0x68, 0xd4, 0xaa, 0x41, 0x99, 0x1a, 0x65, 0x1a,
|
|
0xd4, 0xea, 0x53, 0xa9, 0x31, 0x63, 0xf3, 0xb5, 0xb4, 0x77, 0x83, 0x40, 0x1c, 0x0a, 0x84, 0x66,
|
|
0xa4, 0x10, 0x88, 0xff, 0xff};
|
|
|
|
ULONG RndismpBinaryMofSize = sizeof(RndismpBinaryMof);
|
|
|
|
#define RNDISMPDeviceOIDGuid \
|
|
{ 0x437cf222,0x72fe,0x11d4, { 0x97,0xf9,0x00,0x20,0x48,0x57,0x03,0x37}}
|
|
|
|
#endif // BINARY_MOF_TEST
|
|
|
|
NDIS_GUID CustomGuidList[] =
|
|
{
|
|
{
|
|
RNDISMPStatisticsOIDGuid,
|
|
OID_RNDISMP_STATISTICS,
|
|
sizeof(UINT32), // size is size of each element in the array
|
|
(fNDIS_GUID_TO_OID|fNDIS_GUID_ARRAY)
|
|
}
|
|
#ifdef BINARY_MOF_TEST
|
|
,
|
|
{
|
|
RNDISMPDeviceOIDGuid,
|
|
OID_RNDISMP_DEVICE_OID,
|
|
sizeof(UINT32),
|
|
fNDIS_GUID_TO_OID
|
|
},
|
|
{
|
|
BINARY_MOF_GUID,
|
|
OID_RNDISMP_GET_MOF_OID,
|
|
sizeof(UINT8),
|
|
(fNDIS_GUID_TO_OID|fNDIS_GUID_ARRAY)
|
|
}
|
|
#endif
|
|
};
|
|
|
|
UINT CustomGuidCount = sizeof(CustomGuidList)/sizeof(NDIS_GUID);
|
|
|
|
/****************************************************************************/
|
|
/* RndismpQueryInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* NDIS Entry point called to handle a query for a particular OID. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* MiniportAdapterContext - a context version of our Adapter pointer */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - a pointer into the NdisRequest->InformationBuffer */
|
|
/* into which store the result of the query. */
|
|
/* InformationBufferLength - a pointer to the number of bytes left in */
|
|
/* the InformationBuffer. */
|
|
/* pBytesWritten - a pointer to the number of bytes written into the */
|
|
/* InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough room in the information buffer */
|
|
/* then this will contain the number of bytes needed to complete the */
|
|
/* request. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
RndismpQueryInformation(IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesWritten,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
PRNDISMP_ADAPTER pAdapter;
|
|
NDIS_STATUS Status;
|
|
|
|
// get adapter context
|
|
pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
|
|
|
CHECK_VALID_ADAPTER(pAdapter);
|
|
|
|
TRACE3(("RndismpQueryInformation\n"));
|
|
|
|
Status = ProcessQueryInformation(pAdapter,
|
|
NULL,
|
|
NULL,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
return Status;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* ProcessQueryInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Utility routine to process a Query (connection-less or connection- */
|
|
/* oriented). */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* pVc - Pointer to a VC, possibly NULL. */
|
|
/* pRequest - Pointer to NDIS request, if this came via our CoRequest */
|
|
/* handler. */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - a pointer into the NdisRequest->InformationBuffer */
|
|
/* into which store the result of the query. */
|
|
/* InformationBufferLength - a pointer to the number of bytes left in */
|
|
/* the InformationBuffer. */
|
|
/* pBytesWritten - a pointer to the number of bytes written into the */
|
|
/* InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough room in the information buffer */
|
|
/* then this will contain the number of bytes needed to complete the */
|
|
/* request. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
ProcessQueryInformation(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_VC pVc,
|
|
IN PNDIS_REQUEST pRequest,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesWritten,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT OIDHandler;
|
|
|
|
OIDHandler = GetOIDSupport(pAdapter, Oid);
|
|
|
|
switch(OIDHandler)
|
|
{
|
|
case DRIVER_SUPPORTED_OID:
|
|
Status = DriverQueryInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
break;
|
|
case DEVICE_SUPPORTED_OID:
|
|
Status = DeviceQueryInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
break;
|
|
case OID_NOT_SUPPORTED:
|
|
default:
|
|
TRACE2(("Invalid Query OID (%08X)\n", Oid));
|
|
Status = NDIS_STATUS_INVALID_OID;
|
|
break;
|
|
}
|
|
|
|
TRACE2(("ProcessQueryInfo: Oid %08X, returning Status %x\n", Oid, Status));
|
|
|
|
return Status;
|
|
} // ProcessQueryInformation
|
|
|
|
|
|
/****************************************************************************/
|
|
/* RndismpSetInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* The RndismpSetInformation processes a Set request for */
|
|
/* NDIS_OIDs that are specific about the Driver. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* MiniportAdapterContext - a context version of our Adapter pointer */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - Holds the data to be set. */
|
|
/* InformationBufferLength - The length of InformationBuffer. */
|
|
/* pBytesRead - If the call is successful, returns the number */
|
|
/* of bytes read from InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough data in InformationBuffer */
|
|
/* to satisfy the OID, returns the amount of storage needed. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
RndismpSetInformation(IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesRead,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
PRNDISMP_ADAPTER pAdapter;
|
|
NDIS_STATUS Status;
|
|
|
|
// get adapter context
|
|
pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
|
|
|
CHECK_VALID_ADAPTER(pAdapter);
|
|
|
|
TRACE3(("RndismpSetInformation\n"));
|
|
|
|
Status = ProcessSetInformation(pAdapter,
|
|
NULL,
|
|
NULL,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesRead,
|
|
pBytesNeeded);
|
|
return Status;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* ProcessSetInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Utility routine to process a Set (connection-less or connection- */
|
|
/* oriented). */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* pVc - Pointer to a VC, possibly NULL. */
|
|
/* pRequest - Pointer to NDIS request, if this came via our CoRequest */
|
|
/* handler. */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - a pointer into the NdisRequest->InformationBuffer */
|
|
/* into which store the result of the query. */
|
|
/* InformationBufferLength - a pointer to the number of bytes left in */
|
|
/* the InformationBuffer. */
|
|
/* pBytesRead - a pointer to the number of bytes read from the */
|
|
/* InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough room in the information buffer */
|
|
/* then this will contain the number of bytes needed to complete the */
|
|
/* request. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
ProcessSetInformation(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_VC pVc OPTIONAL,
|
|
IN PNDIS_REQUEST pRequest OPTIONAL,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesRead,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
NDIS_STATUS Status;
|
|
UINT OIDHandler;
|
|
|
|
OIDHandler = GetOIDSupport(pAdapter, Oid);
|
|
|
|
switch(OIDHandler)
|
|
{
|
|
case DRIVER_SUPPORTED_OID:
|
|
Status = DriverSetInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesRead,
|
|
pBytesNeeded);
|
|
break;
|
|
|
|
case DEVICE_SUPPORTED_OID:
|
|
Status = DeviceSetInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesRead,
|
|
pBytesNeeded);
|
|
break;
|
|
|
|
case OID_NOT_SUPPORTED:
|
|
default:
|
|
TRACE2(("Invalid Set OID (%08X), Adapter %p\n", Oid, pAdapter));
|
|
Status = NDIS_STATUS_INVALID_OID;
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
} // ProcessSetInformation
|
|
|
|
/****************************************************************************/
|
|
/* DriverQueryInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* The RndismpQueryInformation processes a Query request for */
|
|
/* NDIS_OIDs that are specific about the Driver. This routine */
|
|
/* Handles OIDs supported by the driver instead of the device */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* pVc - Pointer to a VC, possibly NULL. */
|
|
/* pRequest - Pointer to NDIS request, if this came via our CoRequest */
|
|
/* handler. */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - a pointer into the NdisRequest->InformationBuffer */
|
|
/* into which store the result of the query. */
|
|
/* InformationBufferLength - a pointer to the number of bytes left in */
|
|
/* the InformationBuffer. */
|
|
/* pBytesWritten - a pointer to the number of bytes written into the */
|
|
/* InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough room in the information buffer */
|
|
/* then this will contain the number of bytes needed to complete the */
|
|
/* request. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
DriverQueryInformation(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_VC pVc OPTIONAL,
|
|
IN PNDIS_REQUEST pRequest OPTIONAL,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesWritten,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PVOID MoveSource;
|
|
UINT MoveBytes;
|
|
ULONG GenericUlong;
|
|
USHORT GenericUshort;
|
|
CHAR VendorDescription[] = "Remote NDIS Network Card";
|
|
|
|
TRACE3(("DriverQueryInformation\n"));
|
|
OID_NAME_TRACE(Oid, "DriverQuery");
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
MoveSource = (PVOID) (&GenericUlong);
|
|
MoveBytes = sizeof(GenericUlong);
|
|
|
|
// this is one we have to handle
|
|
switch(Oid)
|
|
{
|
|
case OID_GEN_DRIVER_VERSION:
|
|
GenericUshort = (pAdapter->DriverBlock->MajorNdisVersion << 8) +
|
|
(pAdapter->DriverBlock->MinorNdisVersion);
|
|
|
|
MoveSource = (PVOID)&GenericUshort;
|
|
MoveBytes = sizeof(GenericUshort);
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_ID:
|
|
TRACE1(("Query for OID_GEN_VENDOR_ID not supported by device!\n"));
|
|
GenericUlong = 0xFFFFFF;
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_DESCRIPTION:
|
|
TRACE1(("Query for OID_GEN_VENDOR_DESCRIPTION not supported by device!\n"));
|
|
if (pAdapter->FriendlyNameAnsi.Length != 0)
|
|
{
|
|
MoveSource = pAdapter->FriendlyNameAnsi.Buffer;
|
|
MoveBytes = pAdapter->FriendlyNameAnsi.Length;
|
|
}
|
|
else
|
|
{
|
|
MoveSource = VendorDescription;
|
|
MoveBytes = sizeof(VendorDescription);
|
|
}
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_DRIVER_VERSION:
|
|
TRACE1(("Query for OID_GEN_VENDOR_DRIVER_VERSION not supported by device!\n"));
|
|
GenericUlong = 0xA000B;
|
|
break;
|
|
|
|
case OID_GEN_MAC_OPTIONS:
|
|
GenericUlong = pAdapter->MacOptions;
|
|
break;
|
|
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
// get the list we generated
|
|
MoveSource = (PVOID) (pAdapter->SupportedOIDList);
|
|
MoveBytes = pAdapter->SupportedOIDListSize;
|
|
break;
|
|
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
Status = DeviceQueryInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
OID_GEN_MEDIA_SUPPORTED,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
Status = DeviceQueryInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
|
|
break;
|
|
|
|
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
|
GenericUlong = pAdapter->MaxTransferSize;
|
|
break;
|
|
|
|
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
|
GenericUlong = pAdapter->MaxReceiveSize * 8;
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
Status = DeviceQueryInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
Status = DeviceQueryInformation(pAdapter,
|
|
pVc,
|
|
pRequest,
|
|
OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
InformationBuffer,
|
|
InformationBufferLength,
|
|
pBytesWritten,
|
|
pBytesNeeded);
|
|
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
TRACE1(("Query for OID_GEN_MAXIMUM_TOTAL_SIZE not supported by device!\n"));
|
|
GenericUlong = (ULONG) MAXIMUM_ETHERNET_PACKET_SIZE;
|
|
break;
|
|
|
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
|
TRACE1(("Query for OID_GEN_TRANSMIT_BLOCK_SIZE not supported by device!\n"));
|
|
GenericUlong = (ULONG) MAXIMUM_ETHERNET_PACKET_SIZE;
|
|
break;
|
|
|
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
|
TRACE1(("Query for OID_GEN_RECEIVE_BLOCK_SIZE not supported by device!\n"));
|
|
GenericUlong = (ULONG) MAXIMUM_ETHERNET_PACKET_SIZE;
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_SEND_PACKETS:
|
|
GenericUlong = (ULONG) pAdapter->MaxPacketsPerMessage;
|
|
break;
|
|
|
|
case OID_PNP_CAPABILITIES:
|
|
case OID_PNP_QUERY_POWER:
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
|
|
case OID_GEN_XMIT_OK:
|
|
GenericUlong = RNDISMP_GET_ADAPTER_STATS(pAdapter, XmitOk);
|
|
break;
|
|
|
|
case OID_GEN_XMIT_ERROR:
|
|
GenericUlong = RNDISMP_GET_ADAPTER_STATS(pAdapter, XmitError);
|
|
break;
|
|
|
|
case OID_GEN_RCV_OK:
|
|
GenericUlong = RNDISMP_GET_ADAPTER_STATS(pAdapter, RecvOk);
|
|
break;
|
|
|
|
case OID_GEN_RCV_ERROR:
|
|
GenericUlong = RNDISMP_GET_ADAPTER_STATS(pAdapter, RecvError);
|
|
break;
|
|
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
GenericUlong = RNDISMP_GET_ADAPTER_STATS(pAdapter, RecvNoBuf);
|
|
break;
|
|
|
|
case OID_GEN_SUPPORTED_GUIDS:
|
|
MoveSource = (PVOID)&CustomGuidList[0];
|
|
MoveBytes = sizeof(CustomGuidList);
|
|
TRACE1(("Query for supported GUIDs, len %d\n", InformationBufferLength));
|
|
break;
|
|
|
|
case OID_RNDISMP_STATISTICS:
|
|
MoveSource = &pAdapter->Statistics;
|
|
MoveBytes = sizeof(pAdapter->Statistics);
|
|
break;
|
|
|
|
#ifdef BINARY_MOF_TEST
|
|
|
|
case OID_RNDISMP_DEVICE_OID:
|
|
DbgPrint("*** RNDISMP: Query for Device OID\n");
|
|
GenericUlong = 0xabcdefab;
|
|
break;
|
|
|
|
case OID_RNDISMP_GET_MOF_OID:
|
|
DbgPrint("*** RNDISMP: Query for MOF Info: Src %p, Size %d\n",
|
|
RndismpBinaryMof, RndismpBinaryMofSize);
|
|
MoveSource = RndismpBinaryMof;
|
|
MoveBytes = RndismpBinaryMofSize;
|
|
break;
|
|
|
|
#endif // BINARY_MOF_TEST
|
|
|
|
#ifdef TESTING
|
|
case OID_TCP_TASK_OFFLOAD:
|
|
DbgPrint("RNDISMP: got query for TCP offload\n");
|
|
MoveSource = pOffloadBuffer;
|
|
MoveBytes = OffloadSize;
|
|
break;
|
|
case OID_GEN_PHYSICAL_MEDIUM:
|
|
DbgPrint("RNDISMP: got query for physical medium\n");
|
|
GenericUlong = NdisPhysicalMediumDSL;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
Status = NDIS_STATUS_INVALID_OID;
|
|
break;
|
|
}
|
|
|
|
// copy stuff to information buffer
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (MoveBytes > InformationBufferLength)
|
|
{
|
|
// Not enough room in InformationBuffer
|
|
*pBytesNeeded = MoveBytes;
|
|
|
|
Status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
|
}
|
|
else
|
|
{
|
|
// Copy result into InformationBuffer
|
|
*pBytesWritten = MoveBytes;
|
|
|
|
if (MoveBytes > 0)
|
|
RNDISMP_MOVE_MEM(InformationBuffer, MoveSource, MoveBytes);
|
|
}
|
|
}
|
|
|
|
TRACE2(("Status (%08X) BytesWritten (%08X)\n", Status, *pBytesWritten));
|
|
|
|
return Status;
|
|
} // DriverQueryInformation
|
|
|
|
/****************************************************************************/
|
|
/* DeviceQueryInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* The DeviceQueryInformation processes a Query request */
|
|
/* that is going to the Remote NDIS device */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - pointer to our Adapter structure */
|
|
/* pVc - optional pointer to our VC structure, if this is a per-Vc req. */
|
|
/* pRequest - optional pointer to NDIS request, if CONDIS. */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - a pointer into the NdisRequest->InformationBuffer */
|
|
/* into which store the result of the query. */
|
|
/* InformationBufferLength - a pointer to the number of bytes left in */
|
|
/* the InformationBuffer. */
|
|
/* pBytesWritten - a pointer to the number of bytes written into the */
|
|
/* InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough room in the information buffer */
|
|
/* then this will contain the number of bytes needed to complete the */
|
|
/* request. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
DeviceQueryInformation(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_VC pVc OPTIONAL,
|
|
IN PNDIS_REQUEST pRequest OPTIONAL,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesWritten,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
PRNDISMP_MESSAGE_FRAME pMsgFrame;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext;
|
|
NDIS_STATUS Status;
|
|
PUCHAR pSrcBuffer;
|
|
ULONG ByteLength;
|
|
|
|
OID_NAME_TRACE(Oid, "DeviceQuery");
|
|
TRACE3(("DeviceQuery: OID %x, InfoBuf %p, Len %d, pBytesWrit %p, pBytesNeed %p\n",
|
|
Oid, InformationBuffer, InformationBufferLength, pBytesWritten, pBytesNeeded));
|
|
|
|
//
|
|
// Debug code for Win9X/WinMe:
|
|
//
|
|
// TRACE1(("DeviceQuery: NdisRequest = %x, AdapterFlags %x, list empty %d\n",
|
|
// *(PULONG)((PUCHAR)pAdapter->MiniportAdapterHandle + 0x13c),
|
|
// *(PULONG)((PUCHAR)pAdapter->MiniportAdapterHandle + 0x3c),
|
|
// IsListEmpty(&pAdapter->PendingFrameList)
|
|
// ));
|
|
// if (!IsListEmpty(&pAdapter->PendingFrameList))
|
|
// {
|
|
// TRACE0(("DeviceQuery: Adapter %p, PendingFrameList @%p not empty!\n",
|
|
// pAdapter, &pAdapter->PendingFrameList));
|
|
// DbgBreakPoint();
|
|
// }
|
|
|
|
do
|
|
{
|
|
if (pAdapter->Halting)
|
|
{
|
|
Status = NDIS_STATUS_NOT_ACCEPTED;
|
|
break;
|
|
}
|
|
|
|
if (pAdapter->bRunningOnWin9x)
|
|
{
|
|
//
|
|
// Intercept some queries to complete them synchronously.
|
|
// This is because NDIS/Win9X-Me has a very short timeout for
|
|
// internally generated queries (the ones intercepted below).
|
|
//
|
|
switch (Oid)
|
|
{
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
pSrcBuffer = (PUCHAR)&pAdapter->MaxMulticastListSize;
|
|
ByteLength = sizeof(pAdapter->MaxMulticastListSize);
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
pSrcBuffer = (PUCHAR)&pAdapter->MaximumFrameSize;
|
|
ByteLength = sizeof(pAdapter->MaximumFrameSize);
|
|
break;
|
|
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
pSrcBuffer = (PUCHAR)pAdapter->MacAddress;
|
|
ByteLength = ETH_LENGTH_OF_ADDRESS;
|
|
break;
|
|
|
|
case OID_GEN_MAC_OPTIONS:
|
|
pSrcBuffer = (PUCHAR)&pAdapter->MacOptions;
|
|
ByteLength = sizeof(pAdapter->MacOptions);
|
|
break;
|
|
|
|
default:
|
|
pSrcBuffer = NULL;
|
|
ByteLength = 0;
|
|
break;
|
|
}
|
|
|
|
if (pSrcBuffer != NULL)
|
|
{
|
|
if (InformationBufferLength < ByteLength)
|
|
{
|
|
*pBytesNeeded = ByteLength;
|
|
Status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
|
}
|
|
else
|
|
{
|
|
TRACE1(("DeviceQuery: Adapter %p, intercepted OID %x\n",
|
|
pAdapter, Oid));
|
|
*pBytesNeeded = *pBytesWritten = ByteLength;
|
|
NdisMoveMemory(InformationBuffer, pSrcBuffer, ByteLength);
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
pReqContext = AllocateRequestContext(pAdapter);
|
|
if (pReqContext == NULL)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// HACKHACK to avoid a strange length from going to the device,
|
|
// we minimize the amount of data sent with the query.
|
|
//
|
|
// In general, there is no point sending a huge information buffer
|
|
// along with a Query that does not require an IN parameter.
|
|
// Long term, we may have to separate out the few OIDs that do
|
|
// use IN parameters and allow those buffers to pass through
|
|
//
|
|
|
|
pMsgFrame = BuildRndisMessageCommon(pAdapter,
|
|
pVc,
|
|
REMOTE_NDIS_QUERY_MSG,
|
|
Oid,
|
|
InformationBuffer,
|
|
((InformationBufferLength > 48)?
|
|
48: InformationBufferLength));
|
|
|
|
// see if we got a message
|
|
if (!pMsgFrame)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
FreeRequestContext(pAdapter, pReqContext);
|
|
break;
|
|
}
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
pReqContext->InformationBuffer = InformationBuffer;
|
|
pReqContext->InformationBufferLength = InformationBufferLength;
|
|
pReqContext->pBytesRead = NULL;
|
|
pReqContext->pBytesWritten = pBytesWritten;
|
|
pReqContext->pBytesNeeded = pBytesNeeded;
|
|
pReqContext->Oid = Oid;
|
|
pReqContext->RetryCount = 0;
|
|
pReqContext->bInternal = FALSE;
|
|
pReqContext->pVc = pVc;
|
|
pReqContext->pNdisRequest = pRequest;
|
|
|
|
pMsgFrame->pReqContext = pReqContext;
|
|
|
|
// Add a ref to keep the frame around until we complete the request.
|
|
ReferenceMsgFrame(pMsgFrame);
|
|
|
|
TRACE3(("DeviceQuery: Oid %x, pReqContext %p, InfoBuf %p, pMsgFrame %p/%d\n",
|
|
Oid, pReqContext, pReqContext->InformationBuffer, pMsgFrame, pMsgFrame->RefCount));
|
|
|
|
// send the message to the microport
|
|
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendDeviceRequest);
|
|
|
|
break;
|
|
}
|
|
while (FALSE);
|
|
|
|
return Status;
|
|
|
|
} // DeviceQueryInformation
|
|
|
|
/****************************************************************************/
|
|
/* DriverSetInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Utility routine to handle SetInformation requests that aren't */
|
|
/* specific to the device. We also land up here for requests for any */
|
|
/* OIDs that aren't supported by the device. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* pVc - Pointer to a VC, possibly NULL. */
|
|
/* pRequest - Pointer to NDIS request, if this came via our CoRequest */
|
|
/* handler. */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - Holds the data to be set. */
|
|
/* InformationBufferLength - The length of InformationBuffer. */
|
|
/* pBytesRead - If the call is successful, returns the number */
|
|
/* of bytes read from InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough data in InformationBuffer */
|
|
/* to satisfy the OID, returns the amount of storage needed. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
DriverSetInformation(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_VC pVc OPTIONAL,
|
|
IN PNDIS_REQUEST pRequest OPTIONAL,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesRead,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
TRACE2(("DriverSetInformation: Adapter %p, Oid %x\n", pAdapter, Oid));
|
|
|
|
OID_NAME_TRACE(Oid, "DriverSet");
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
switch(Oid)
|
|
{
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
// Verify the Length
|
|
if(InformationBufferLength != sizeof(ULONG))
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
*pBytesRead = sizeof(ULONG);
|
|
break;
|
|
|
|
case OID_PNP_SET_POWER:
|
|
case OID_PNP_ADD_WAKE_UP_PATTERN:
|
|
case OID_PNP_REMOVE_WAKE_UP_PATTERN:
|
|
case OID_PNP_ENABLE_WAKE_UP:
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
|
|
#ifdef TESTING
|
|
case OID_TCP_TASK_OFFLOAD:
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
DbgPrint("RNDISMP: Set TCP_TASK_OFFLOAD\n");
|
|
break;
|
|
case OID_GEN_TRANSPORT_HEADER_OFFSET:
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
#endif
|
|
default:
|
|
Status = NDIS_STATUS_INVALID_OID;
|
|
break;
|
|
}
|
|
|
|
TRACE2(("Status (%08X) BytesRead (%08X)\n", Status, *pBytesRead));
|
|
|
|
return Status;
|
|
} // DriverSetInformation
|
|
|
|
/****************************************************************************/
|
|
/* DeviceSetInformation */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* The DeviceSetInformation processes a set request */
|
|
/* that is going to the Remote NDIS device */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - pointer to our Adapter structure */
|
|
/* pVc - optional pointer to our VC structure, if this is a per-Vc req. */
|
|
/* pRequest - optional pointer to NDIS request, if CONDIS. */
|
|
/* Oid - the NDIS_OID to process. */
|
|
/* InformationBuffer - Holds the data to be set. */
|
|
/* InformationBufferLength - The length of InformationBuffer. */
|
|
/* pBytesRead - If the call is successful, returns the number */
|
|
/* of bytes read from InformationBuffer. */
|
|
/* pBytesNeeded - If there is not enough data in InformationBuffer */
|
|
/* to satisfy the OID, returns the amount of storage needed. */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
DeviceSetInformation(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_VC pVc OPTIONAL,
|
|
IN PNDIS_REQUEST pRequest OPTIONAL,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG pBytesRead,
|
|
OUT PULONG pBytesNeeded)
|
|
{
|
|
PRNDISMP_MESSAGE_FRAME pMsgFrame;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext;
|
|
NDIS_STATUS Status;
|
|
|
|
TRACE2(("DeviceSetInformation: Adapter %p, Oid %x\n"));
|
|
|
|
OID_NAME_TRACE(Oid, "DeviceSet");
|
|
|
|
#if DBG
|
|
if (Oid == OID_GEN_CURRENT_PACKET_FILTER)
|
|
{
|
|
PULONG pFilter = (PULONG)InformationBuffer;
|
|
|
|
TRACE1(("DeviceSetInfo: Adapter %p: Setting packet filter to %x\n",
|
|
pAdapter, *pFilter));
|
|
}
|
|
#endif
|
|
|
|
do
|
|
{
|
|
if (pAdapter->Halting)
|
|
{
|
|
TRACE1(("DeviceSetInfo: Adapter %p is halting: succeeding Oid %x\n",
|
|
pAdapter, Oid));
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
pReqContext = AllocateRequestContext(pAdapter);
|
|
if (pReqContext == NULL)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
pMsgFrame = BuildRndisMessageCommon(pAdapter,
|
|
pVc,
|
|
REMOTE_NDIS_SET_MSG,
|
|
Oid,
|
|
InformationBuffer,
|
|
InformationBufferLength);
|
|
|
|
// see if we got a message
|
|
if (!pMsgFrame)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
FreeRequestContext(pAdapter, pReqContext);
|
|
break;
|
|
}
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
pReqContext->InformationBuffer = InformationBuffer;
|
|
pReqContext->InformationBufferLength = InformationBufferLength;
|
|
pReqContext->pBytesRead = pBytesRead;
|
|
pReqContext->pBytesWritten = NULL;
|
|
pReqContext->pBytesNeeded = pBytesNeeded;
|
|
pReqContext->Oid = Oid;
|
|
pReqContext->RetryCount = 0;
|
|
pReqContext->bInternal = FALSE;
|
|
pReqContext->pVc = pVc;
|
|
pReqContext->pNdisRequest = pRequest;
|
|
|
|
pMsgFrame->pReqContext = pReqContext;
|
|
|
|
#ifndef BUILD_WIN9X
|
|
// Add a ref to keep the frame around until we complete the request.
|
|
ReferenceMsgFrame(pMsgFrame);
|
|
|
|
// send the message to the microport
|
|
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendDeviceRequest);
|
|
#else
|
|
//
|
|
// Win9X!
|
|
//
|
|
// Special-case for setting the current packet filter to 0.
|
|
// We complete this one synchronously, otherwise NdisCloseAdapter
|
|
// doesn't seem to complete.
|
|
//
|
|
if ((Oid == OID_GEN_CURRENT_PACKET_FILTER )
|
|
&&
|
|
( (*(PULONG)InformationBuffer == 0) || (pAdapter->bRunningOnWin98Gold) ))
|
|
{
|
|
//
|
|
// Do not queue the request, so that when we get a completion
|
|
// from the device, we simply drop it.
|
|
//
|
|
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, CompleteSendDiscardDeviceRequest);
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// Add a ref to keep the frame around until we complete the request.
|
|
ReferenceMsgFrame(pMsgFrame);
|
|
|
|
// send the message to the microport
|
|
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendDeviceRequest);
|
|
}
|
|
|
|
#endif // BUILD_WIN9X
|
|
break;
|
|
}
|
|
while (FALSE);
|
|
|
|
return Status;
|
|
} // DeviceSetInformation
|
|
|
|
|
|
/****************************************************************************/
|
|
/* QuerySetCompletionMessage */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Completion message from microport in response to query or set message */
|
|
/* miniport sent. This information is now ready to pass to upper layers */
|
|
/* since the original call into the miniport returned STATUS_PENDING */
|
|
/* */
|
|
/* Danger Danger - an OID_GEN_SUPPORTED_LIST query is special cased here */
|
|
/* This is only sent to the device from the adapter init routine to build */
|
|
/* a list of OIDs supported by the driver and device. */
|
|
/* All OID_GEN_SUPPORTED_LIST queries from upper layers are handled by */
|
|
/* the driver and not the device. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* pMessage - pointer to RNDIS message */
|
|
/* pMdl - pointer to MDL from microport */
|
|
/* TotalLength - length of complete message */
|
|
/* MicroportMessageContext - context for message from microport */
|
|
/* ReceiveStatus - used by microport to indicate it is low on resource */
|
|
/* bMessageCopied - is this a copy of the original message? */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* BOOLEAN - should the message be returned to the microport? */
|
|
/* */
|
|
/****************************************************************************/
|
|
BOOLEAN
|
|
QuerySetCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDIS_MESSAGE pMessage,
|
|
IN PMDL pMdl,
|
|
IN ULONG TotalLength,
|
|
IN NDIS_HANDLE MicroportMessageContext,
|
|
IN NDIS_STATUS ReceiveStatus,
|
|
IN BOOLEAN bMessageCopied)
|
|
{
|
|
PRNDISMP_MESSAGE_FRAME pMsgFrame;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext;
|
|
PRNDIS_QUERY_COMPLETE pQueryComplMessage;
|
|
PRNDIS_SET_COMPLETE pSetComplMessage;
|
|
UINT32 NdisMessageType;
|
|
NDIS_STATUS Status;
|
|
UINT BytesWritten;
|
|
UINT BytesRead;
|
|
BOOLEAN bInternal;
|
|
|
|
TRACE3(("QuerySetCompletionMessage\n"));
|
|
|
|
pReqContext = NULL;
|
|
pMsgFrame = NULL;
|
|
|
|
pQueryComplMessage = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
|
|
pSetComplMessage = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
|
|
bInternal = FALSE;
|
|
NdisMessageType = 0xdead;
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
do
|
|
{
|
|
// get request frame from request ID in message
|
|
RNDISMP_LOOKUP_PENDING_MESSAGE(pMsgFrame, pAdapter, pQueryComplMessage->RequestId);
|
|
|
|
if (pMsgFrame == NULL)
|
|
{
|
|
// invalid request ID or aborted request.
|
|
TRACE1(("Invalid/aborted request ID %08X in Query/Set Complete msg %p\n",
|
|
pQueryComplMessage->RequestId, pQueryComplMessage));
|
|
break;
|
|
}
|
|
|
|
pReqContext = pMsgFrame->pReqContext;
|
|
ASSERT(pReqContext != NULL);
|
|
bInternal = pReqContext->bInternal;
|
|
|
|
NdisMessageType = pMessage->NdisMessageType;
|
|
|
|
if (NdisMessageType != RNDIS_COMPLETION(pMsgFrame->NdisMessageType))
|
|
{
|
|
TRACE1(("Query/Response mismatch: Msg @ %p, ReqId %d, req type %X, compl type %X\n",
|
|
pMessage,
|
|
pQueryComplMessage->RequestId,
|
|
pMsgFrame->NdisMessageType,
|
|
NdisMessageType));
|
|
ASSERT(FALSE);
|
|
pMsgFrame = NULL;
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
switch(NdisMessageType)
|
|
{
|
|
// a query complete message indicates we have a response
|
|
// to a query message the miniport sent down. we carry around
|
|
// appropriate context so we can indicate the completion
|
|
// to upper layers and pass the query data up
|
|
//
|
|
// OID_GEN_SUPPORTED_LIST is a special case since it
|
|
// is never indicated to upper layers from the device
|
|
|
|
case REMOTE_NDIS_QUERY_CMPLT:
|
|
|
|
// an OID_GEN_SUPPORTED_LIST is never completed to the upper
|
|
// layers. This is sent from our adapter init routine
|
|
// in preparation for building a list of OIDs
|
|
|
|
TRACE2(("QueryCompl: pReqContext %p, OID %08X, pMsgFrame %p, %d bytes, Status %x\n",
|
|
pReqContext,
|
|
pReqContext->Oid,
|
|
pMsgFrame,
|
|
pQueryComplMessage->InformationBufferLength,
|
|
pQueryComplMessage->Status));
|
|
|
|
pReqContext->CompletionStatus = pQueryComplMessage->Status;
|
|
if (pReqContext->Oid == OID_GEN_SUPPORTED_LIST)
|
|
{
|
|
if (pReqContext->CompletionStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
// Build a list of supported OIDs.
|
|
|
|
TRACE1(("QueryComplete: SupportedList: InfoBufLength %d (%d OIDs)\n",
|
|
pQueryComplMessage->InformationBufferLength,
|
|
pQueryComplMessage->InformationBufferLength/sizeof(NDIS_OID)));
|
|
|
|
Status = BuildOIDLists(pAdapter,
|
|
(PNDIS_OID) (((PUCHAR)(pQueryComplMessage)) +
|
|
pQueryComplMessage->InformationBufferOffset),
|
|
pQueryComplMessage->InformationBufferLength / sizeof(NDIS_OID),
|
|
pAdapter->DriverOIDList,
|
|
pAdapter->NumDriverOIDs);
|
|
|
|
}
|
|
|
|
// the adapter init routine is waiting for a response
|
|
NdisSetEvent(pReqContext->pEvent);
|
|
|
|
break;
|
|
}
|
|
|
|
// something other than OID_GEN_SUPPORTED_LIST
|
|
*pReqContext->pBytesNeeded = pQueryComplMessage->InformationBufferLength;
|
|
|
|
if (pQueryComplMessage->InformationBufferLength > pReqContext->InformationBufferLength)
|
|
{
|
|
TRACE0(("Query Complete (Oid = %08X): InfoBuffLen %d < %d\n",
|
|
pReqContext->Oid,
|
|
pQueryComplMessage->InformationBufferLength,
|
|
pReqContext->InformationBufferLength));
|
|
|
|
Status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
|
break;
|
|
}
|
|
|
|
if (pQueryComplMessage->Status != RNDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE0(("Query Complete (Oid = %08X): error status %08X\n",
|
|
pReqContext->Oid, pQueryComplMessage->Status));
|
|
|
|
*pReqContext->pBytesNeeded = pQueryComplMessage->InformationBufferLength;
|
|
*pReqContext->pBytesWritten = 0;
|
|
Status = pQueryComplMessage->Status;
|
|
}
|
|
else
|
|
{
|
|
// copy information from RNDIS message to NDIS buffer passed down
|
|
TRACE2(("QueryCompl: copy %d bytes to %p\n",
|
|
pQueryComplMessage->InformationBufferLength,
|
|
pReqContext->InformationBuffer));
|
|
|
|
RNDISMP_MOVE_MEM(pReqContext->InformationBuffer,
|
|
MESSAGE_TO_INFO_BUFFER(pQueryComplMessage),
|
|
pQueryComplMessage->InformationBufferLength);
|
|
|
|
// tell the upper layers the size
|
|
*pReqContext->pBytesWritten = pQueryComplMessage->InformationBufferLength;
|
|
|
|
BytesWritten = *pReqContext->pBytesWritten;
|
|
TRACE3(("Query Compl OK: Adapter %p, Oid %x\n",
|
|
pAdapter, pReqContext->Oid));
|
|
|
|
TRACE2(("Info Data (%08X)\n", *((PUINT) pReqContext->InformationBuffer)));
|
|
|
|
if (pReqContext->Oid == OID_GEN_MEDIA_CONNECT_STATUS)
|
|
{
|
|
TRACE3(("Adapter %p: link is %s\n",
|
|
pAdapter, (((*(PULONG)pReqContext->InformationBuffer) == NdisMediaStateConnected)?
|
|
"Connected": "Not connected")));
|
|
}
|
|
|
|
if (pReqContext->Oid == OID_GEN_MAC_OPTIONS)
|
|
{
|
|
PULONG pMacOptions = (PULONG)pReqContext->InformationBuffer;
|
|
ULONG MacOptions = *pMacOptions;
|
|
|
|
TRACE1(("Adapter %p: OID_GEN_MAC_OPTIONS from device is %x\n",
|
|
pAdapter, MacOptions));
|
|
//
|
|
// We only let the device dictate some of these bits.
|
|
//
|
|
MacOptions = (MacOptions & RNDIS_DEVICE_MAC_OPTIONS_MASK) |
|
|
pAdapter->MacOptions;
|
|
|
|
*pMacOptions = MacOptions;
|
|
|
|
TRACE1(("Adapter %p: Modified OID_GEN_MAC_OPTIONS is %x\n",
|
|
pAdapter, *pMacOptions));
|
|
}
|
|
|
|
|
|
#if 0
|
|
//
|
|
// Temp hack for old-firmware Peracom devices - report a smaller
|
|
// value for max multicast list aize.
|
|
//
|
|
if (pReqContext->Oid == OID_802_3_MAXIMUM_LIST_SIZE)
|
|
{
|
|
PULONG pListSize = (PULONG)pReqContext->InformationBuffer;
|
|
if (*pListSize > 64)
|
|
{
|
|
|
|
TRACE1(("Adapter %p: Truncating max multicast list size from %d to 63!\n",
|
|
pAdapter, *pListSize));
|
|
*pListSize = 64;
|
|
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// If this is an internally generated query,
|
|
// wake up the originating thread - that thread will
|
|
// take care of freeing resources.
|
|
//
|
|
if (bInternal && pReqContext->pEvent)
|
|
{
|
|
NdisSetEvent(pReqContext->pEvent);
|
|
pMsgFrame = NULL;
|
|
pReqContext = NULL;
|
|
}
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case REMOTE_NDIS_SET_CMPLT:
|
|
|
|
TRACE2(("SetCompl: OID %08X, pReq %p, Status %x\n",
|
|
pReqContext->Oid,
|
|
pReqContext,
|
|
pSetComplMessage->Status));
|
|
|
|
if (pSetComplMessage->Status == RNDIS_STATUS_SUCCESS)
|
|
{
|
|
*pReqContext->pBytesRead = pReqContext->InformationBufferLength;
|
|
BytesRead = *pReqContext->pBytesRead;
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// don't really expect to see this other than via NDISTEST
|
|
|
|
TRACE1(("Set Complete (Oid = %08X) failure: %08X\n",
|
|
pReqContext->Oid,
|
|
pSetComplMessage->Status));
|
|
|
|
*pReqContext->pBytesRead = 0;
|
|
BytesRead = 0;
|
|
Status = pSetComplMessage->Status;
|
|
}
|
|
|
|
pReqContext->CompletionStatus = Status;
|
|
|
|
if (bInternal && pReqContext->pEvent)
|
|
{
|
|
NdisSetEvent(pReqContext->pEvent);
|
|
pMsgFrame = NULL;
|
|
pReqContext = NULL;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
TRACE1(("Invalid Ndis Message Type (%08X)\n", NdisMessageType));
|
|
ASSERT(FALSE); // we shouldn't have sent an invalid message type!
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
while (FALSE);
|
|
|
|
//
|
|
// Send the completion to the upper layers unless it was a request
|
|
// we generated outselves.
|
|
//
|
|
if (!bInternal && pReqContext)
|
|
{
|
|
if (pReqContext->pNdisRequest)
|
|
{
|
|
NdisMCoRequestComplete(Status,
|
|
pAdapter->MiniportAdapterHandle,
|
|
pReqContext->pNdisRequest);
|
|
}
|
|
else
|
|
{
|
|
if (NdisMessageType == REMOTE_NDIS_QUERY_CMPLT)
|
|
{
|
|
TRACE3(("Status (%08X) BytesWritten (%08X)\n", Status, BytesWritten));
|
|
|
|
// complete the query
|
|
|
|
NdisMQueryInformationComplete(pAdapter->MiniportAdapterHandle,
|
|
Status);
|
|
}
|
|
else if (NdisMessageType == REMOTE_NDIS_SET_CMPLT)
|
|
{
|
|
TRACE3(("Status (%08X) BytesRead (%08X)\n", Status, BytesRead));
|
|
|
|
// complete the set
|
|
NdisMSetInformationComplete(pAdapter->MiniportAdapterHandle,
|
|
Status);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pReqContext)
|
|
{
|
|
FreeRequestContext(pAdapter, pReqContext);
|
|
}
|
|
|
|
if (pMsgFrame)
|
|
{
|
|
DereferenceMsgFrame(pMsgFrame);
|
|
}
|
|
|
|
return (TRUE);
|
|
|
|
} // QuerySetCompletionMessage
|
|
|
|
/****************************************************************************/
|
|
/* CompleteSendDeviceRequest */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Completion of send of a device set or query request thru the microport. */
|
|
/* If the message send failed, complete the request right now. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pMsgFrame - our context for the message */
|
|
/* SendStatus - microport's send status */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* None. */
|
|
/* */
|
|
/****************************************************************************/
|
|
VOID
|
|
CompleteSendDeviceRequest(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
|
|
IN NDIS_STATUS SendStatus)
|
|
{
|
|
PRNDISMP_ADAPTER pAdapter;
|
|
PRNDISMP_MESSAGE_FRAME pOrgMsgFrame;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext;
|
|
UINT NdisMessageType;
|
|
|
|
pAdapter = pMsgFrame->pAdapter;
|
|
|
|
TRACE3(("CompleteSendDevice Request: Adapter %p, MsgFrame %p, Status %x\n",
|
|
pAdapter, pMsgFrame, SendStatus));
|
|
|
|
if (SendStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Microport failed to send the Request message;
|
|
// attempt to fail the original NDIS request.
|
|
//
|
|
TRACE1(("CompleteSendDeviceReq: Adapter %p, MsgFrame %p, failed %x\n",
|
|
pAdapter, pMsgFrame, SendStatus));
|
|
|
|
RNDISMP_LOOKUP_PENDING_MESSAGE(pOrgMsgFrame, pAdapter, pMsgFrame->RequestId);
|
|
|
|
if (pOrgMsgFrame == pMsgFrame)
|
|
{
|
|
//
|
|
// The request has not been aborted, so complete it now.
|
|
//
|
|
pReqContext = pMsgFrame->pReqContext;
|
|
NdisMessageType = pMsgFrame->NdisMessageType;
|
|
|
|
TRACE1(("CompleteSendReq: Adapter %p: Device req send failed, Oid %x, retry count %d\n",
|
|
pAdapter, pReqContext->Oid, pReqContext->RetryCount));
|
|
|
|
if (NdisMessageType == REMOTE_NDIS_QUERY_MSG)
|
|
{
|
|
// complete the query
|
|
NdisMQueryInformationComplete(pAdapter->MiniportAdapterHandle,
|
|
SendStatus);
|
|
}
|
|
else if (NdisMessageType == REMOTE_NDIS_SET_MSG)
|
|
{
|
|
// complete the set
|
|
NdisMSetInformationComplete(pAdapter->MiniportAdapterHandle,
|
|
SendStatus);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
FreeRequestContext(pAdapter, pReqContext);
|
|
pMsgFrame->pReqContext = (PRNDISMP_REQUEST_CONTEXT)UlongToPtr(0xbcbcbcbc);
|
|
|
|
//
|
|
// Deref for NDIS request completion:
|
|
//
|
|
DereferenceMsgFrame(pMsgFrame);
|
|
}
|
|
//
|
|
// else we failed to locate the request on the pending list;
|
|
// it must have been removed when aborting all requests due
|
|
// to a reset.
|
|
//
|
|
}
|
|
//
|
|
// else sent the message out successfully; wait for a response.
|
|
//
|
|
|
|
//
|
|
// Deref for send-complete:
|
|
//
|
|
DereferenceMsgFrame(pMsgFrame);
|
|
}
|
|
|
|
#ifdef BUILD_WIN9X
|
|
/****************************************************************************/
|
|
/* CompleteSendDiscardDeviceRequest */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Completion of send of a device set or query request thru the microport. */
|
|
/* The sender of the request just wants us to free it up here. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pMsgFrame - our context for the message */
|
|
/* SendStatus - microport's send status */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* None. */
|
|
/* */
|
|
/****************************************************************************/
|
|
VOID
|
|
CompleteSendDiscardDeviceRequest(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
|
|
IN NDIS_STATUS SendStatus)
|
|
{
|
|
PRNDISMP_ADAPTER pAdapter;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext;
|
|
|
|
pAdapter = pMsgFrame->pAdapter;
|
|
pReqContext = pMsgFrame->pReqContext;
|
|
|
|
TRACE1(("CompleteSendDiscard: Adapter %p, MsgFrame %p, ReqContext %p\n",
|
|
pAdapter, pMsgFrame, pReqContext));
|
|
|
|
FreeRequestContext(pAdapter, pReqContext);
|
|
DereferenceMsgFrame(pMsgFrame);
|
|
}
|
|
#endif // BUILD_WIN9X
|
|
|
|
/****************************************************************************/
|
|
/* BuildOIDLists */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Build list of supported OIDs and associated function pointers */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* Adapter - Adapter object */
|
|
/* DeviceOIDList - list of OIDs supported by the device */
|
|
/* NumDeviceOID - number of OIDs supported by device */
|
|
/* DriverOIDList - list of OIDs supported by the driver */
|
|
/* NumDriverOID - number of OIDs supported by driver */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
BuildOIDLists(IN PRNDISMP_ADAPTER Adapter,
|
|
IN PNDIS_OID DeviceOIDList,
|
|
IN UINT NumDeviceOID,
|
|
IN PNDIS_OID DriverOIDList,
|
|
IN UINT NumDriverOID)
|
|
{
|
|
UINT DeviceIndex;
|
|
UINT DriverIndex;
|
|
UINT NumOID;
|
|
NDIS_STATUS Status;
|
|
PNDIS_OID OIDList;
|
|
PUINT OIDHandlerList;
|
|
|
|
TRACE3(("BuildOIDLists\n"));
|
|
|
|
ASSERT(DeviceOIDList);
|
|
ASSERT(DriverOIDList);
|
|
|
|
NumOID = NumDriverOID;
|
|
|
|
// see what OIDs are duplicated in the device and route
|
|
// those to the device
|
|
for(DeviceIndex = 0; DeviceIndex < NumDeviceOID; DeviceIndex++)
|
|
{
|
|
for(DriverIndex = 0; DriverIndex < NumDriverOID; DriverIndex++)
|
|
{
|
|
if(DeviceOIDList[DeviceIndex] == DriverOIDList[DriverIndex])
|
|
{
|
|
// this OID is supported by the device, so don't
|
|
// support in the driver, set to 0 for when we build new list
|
|
DriverOIDList[DriverIndex] = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if no match, increment the OID count
|
|
if(DriverIndex == NumDriverOID)
|
|
NumOID++;
|
|
}
|
|
|
|
// allocate OID list
|
|
Status = MemAlloc(&Adapter->SupportedOIDList,
|
|
NumOID * sizeof(NDIS_OID));
|
|
|
|
// see if we got our buffer
|
|
if(Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Adapter->SupportedOIDListSize = NumOID * sizeof(NDIS_OID);
|
|
}
|
|
else
|
|
{
|
|
Adapter->OIDHandlerList = (PUINT) NULL;
|
|
Adapter->OIDHandlerListSize = 0;
|
|
|
|
Adapter->SupportedOIDList = (PNDIS_OID) NULL;
|
|
Adapter->SupportedOIDListSize = 0;
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
|
|
goto BuildDone;
|
|
}
|
|
|
|
// allocate list to indicate whether the OID is device or driver supported
|
|
Status = MemAlloc(&Adapter->OIDHandlerList,
|
|
NumOID * sizeof(UINT));
|
|
|
|
// see if we got our buffer
|
|
if(Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Adapter->OIDHandlerListSize = NumOID * sizeof(UINT);
|
|
}
|
|
else
|
|
{
|
|
// free up allocated OID list cause this allocation failed
|
|
MemFree(Adapter->SupportedOIDList, Adapter->SupportedOIDListSize);
|
|
|
|
Adapter->OIDHandlerList = (PUINT) NULL;
|
|
Adapter->OIDHandlerListSize = 0;
|
|
|
|
Adapter->SupportedOIDList = (PNDIS_OID) NULL;
|
|
Adapter->SupportedOIDListSize = 0;
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
|
|
goto BuildDone;
|
|
}
|
|
|
|
Adapter->NumOIDSupported = NumOID;
|
|
OIDHandlerList = Adapter->OIDHandlerList;
|
|
OIDList = Adapter->SupportedOIDList;
|
|
|
|
// O.K., build our lists
|
|
for(DriverIndex = 0; DriverIndex < NumDriverOID; DriverIndex++)
|
|
{
|
|
if(DriverOIDList[DriverIndex] != 0)
|
|
{
|
|
// got one, so add to the list
|
|
*OIDList = DriverOIDList[DriverIndex];
|
|
OIDList++;
|
|
|
|
// set flag
|
|
*OIDHandlerList = DRIVER_SUPPORTED_OID;
|
|
OIDHandlerList++;
|
|
}
|
|
}
|
|
|
|
// let's add device supported OIDs
|
|
for(DeviceIndex = 0; DeviceIndex < NumDeviceOID; DeviceIndex++)
|
|
{
|
|
if(DeviceOIDList[DeviceIndex] != 0)
|
|
{
|
|
// got one, so add to the list
|
|
*OIDList = DeviceOIDList[DeviceIndex];
|
|
OIDList++;
|
|
|
|
// set flag
|
|
*OIDHandlerList = DEVICE_SUPPORTED_OID;
|
|
OIDHandlerList++;
|
|
}
|
|
}
|
|
|
|
// Now do a fixup to point OID_GEN_SUPPORTED_LIST at the driver since
|
|
// we now have a complete list.
|
|
//
|
|
for(DeviceIndex = 0; DeviceIndex < Adapter->NumOIDSupported; DeviceIndex++)
|
|
{
|
|
if (Adapter->SupportedOIDList[DeviceIndex] == OID_GEN_SUPPORTED_LIST)
|
|
{
|
|
Adapter->OIDHandlerList[DeviceIndex] = DRIVER_SUPPORTED_OID;
|
|
}
|
|
}
|
|
|
|
BuildDone:
|
|
|
|
if(Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
DISPLAY_OID_LIST(Adapter);
|
|
}
|
|
|
|
return Status;
|
|
} // BuildOIDLists
|
|
|
|
/****************************************************************************/
|
|
/* GetOIDSupport */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Returns flag to indicate if OID is device or driver supported */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* Adapter - Adapter object */
|
|
/* Oid - looking for a match on this OID */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* UINT */
|
|
/* */
|
|
/****************************************************************************/
|
|
UINT
|
|
GetOIDSupport(IN PRNDISMP_ADAPTER Adapter, IN NDIS_OID Oid)
|
|
{
|
|
UINT Index;
|
|
|
|
TRACE3(("GetOIDSupport\n"));
|
|
|
|
// sanity check
|
|
ASSERT(Adapter->SupportedOIDList);
|
|
ASSERT(Adapter->OIDHandlerList);
|
|
|
|
// search for a match on the OID
|
|
for(Index = 0; Index < Adapter->NumOIDSupported; Index++)
|
|
{
|
|
if(Adapter->SupportedOIDList[Index] == Oid)
|
|
{
|
|
return Adapter->OIDHandlerList[Index];
|
|
}
|
|
}
|
|
|
|
return OID_NOT_SUPPORTED;
|
|
} // GetOIDSupport
|
|
|
|
|
|
/****************************************************************************/
|
|
/* FreeOIDLists */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Free OID and handler lists */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* Adapter - Adapter object */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* VOID */
|
|
/* */
|
|
/****************************************************************************/
|
|
VOID
|
|
FreeOIDLists(IN PRNDISMP_ADAPTER Adapter)
|
|
{
|
|
UINT Size1, Size2;
|
|
PUCHAR Buffer1, Buffer2;
|
|
|
|
TRACE3(("FreeOIDLists\n"));
|
|
|
|
// grab the spinlock
|
|
NdisAcquireSpinLock(&Adapter->Lock);
|
|
|
|
Buffer1 = (PUCHAR) Adapter->SupportedOIDList;
|
|
Size1 = Adapter->SupportedOIDListSize;
|
|
|
|
Buffer2 = (PUCHAR) Adapter->OIDHandlerList;
|
|
Size2 = Adapter->OIDHandlerListSize;
|
|
|
|
Adapter->SupportedOIDList = (PUINT) NULL;
|
|
Adapter->SupportedOIDListSize = 0;
|
|
|
|
Adapter->OIDHandlerList = (PUINT) NULL;
|
|
Adapter->OIDHandlerListSize = 0;
|
|
Adapter->NumOIDSupported = 0;
|
|
|
|
// release spinlock
|
|
NdisReleaseSpinLock(&Adapter->Lock);
|
|
|
|
if(Buffer1)
|
|
MemFree(Buffer1, Size1);
|
|
|
|
if(Buffer2)
|
|
MemFree(Buffer2, Size2);
|
|
|
|
} // FreeOIDLists
|
|
|
|
/****************************************************************************/
|
|
/* AllocateRequestContext */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Allocate a context structure to keep track of an NDIS request */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* PRNDISMP_REQUEST_CONTEXT */
|
|
/* */
|
|
/****************************************************************************/
|
|
PRNDISMP_REQUEST_CONTEXT
|
|
AllocateRequestContext(IN PRNDISMP_ADAPTER pAdapter)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext;
|
|
|
|
Status = MemAlloc(&pReqContext, sizeof(RNDISMP_REQUEST_CONTEXT));
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
pReqContext = NULL;
|
|
}
|
|
|
|
TRACE3(("AllocReqContext: %p\n", pReqContext));
|
|
|
|
return pReqContext;
|
|
} // AllocateRequestContext
|
|
|
|
|
|
/****************************************************************************/
|
|
/* FreeRequestContext */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Freeing up miniport resources associated with a request */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* pReqContext - Pointer to request context to be freed */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* VOID */
|
|
/* */
|
|
/****************************************************************************/
|
|
VOID
|
|
FreeRequestContext(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN PRNDISMP_REQUEST_CONTEXT pReqContext)
|
|
{
|
|
|
|
TRACE3(("FreeReqContext: %p\n", pReqContext));
|
|
|
|
MemFree(pReqContext, -1);
|
|
} // FreeRequestContext
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
/* SyncQueryDevice */
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Routine Description: */
|
|
/* */
|
|
/* Init-time routine called to query the device for an OID, and wait */
|
|
/* until we get a response. */
|
|
/* */
|
|
/* Arguments: */
|
|
/* */
|
|
/* pAdapter - Pointer to our adapter structure */
|
|
/* Oid - Object Identifier to be queried */
|
|
/* InformationBuffer - buffer to copy query response into */
|
|
/* InformationBufferLength - length of the above */
|
|
/* */
|
|
/* Return: */
|
|
/* */
|
|
/* NDIS_STATUS_SUCCESS if successful, NDIS_STATUS_xxx error otherwise */
|
|
/* */
|
|
/****************************************************************************/
|
|
NDIS_STATUS
|
|
SyncQueryDevice(IN PRNDISMP_ADAPTER pAdapter,
|
|
IN NDIS_OID Oid,
|
|
IN OUT PUCHAR InformationBuffer,
|
|
IN ULONG InformationBufferLength)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL;
|
|
PRNDISMP_MESSAGE_FRAME pPendingMsgFrame;
|
|
PRNDISMP_REQUEST_CONTEXT pReqContext = NULL;
|
|
RNDIS_REQUEST_ID RequestId;
|
|
NDIS_EVENT Event;
|
|
BOOLEAN bWokenUp;
|
|
ULONG BytesNeeded, BytesWritten;
|
|
|
|
do
|
|
{
|
|
pReqContext = AllocateRequestContext(pAdapter);
|
|
if (pReqContext == NULL)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Build a query message for the specified OID.
|
|
//
|
|
pMsgFrame = BuildRndisMessageCommon(pAdapter,
|
|
NULL,
|
|
REMOTE_NDIS_QUERY_MSG,
|
|
Oid,
|
|
(PVOID) NULL,
|
|
0);
|
|
|
|
if (pMsgFrame == NULL)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Context for the request - mark this as an internally generated
|
|
// request.
|
|
//
|
|
pReqContext->pNdisRequest = NULL;
|
|
pReqContext->Oid = Oid;
|
|
pReqContext->InformationBuffer = InformationBuffer;
|
|
pReqContext->InformationBufferLength = InformationBufferLength;
|
|
pReqContext->pBytesNeeded = &BytesNeeded;
|
|
pReqContext->pBytesWritten = &BytesWritten;
|
|
pReqContext->pBytesRead = NULL;
|
|
pReqContext->bInternal = TRUE;
|
|
pReqContext->CompletionStatus = NDIS_STATUS_DEVICE_FAILED;
|
|
|
|
NdisInitializeEvent(&Event);
|
|
pReqContext->pEvent = &Event;
|
|
|
|
pMsgFrame->pVc = NULL;
|
|
pMsgFrame->pReqContext = pReqContext;
|
|
|
|
RequestId = pMsgFrame->RequestId;
|
|
|
|
// send the message to the microport.
|
|
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, NULL);
|
|
|
|
RNDISMP_ASSERT_AT_PASSIVE();
|
|
bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
|
|
|
|
// remove the message from the pending queue - it may or may not be there.
|
|
RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, pAdapter, RequestId);
|
|
|
|
if (!bWokenUp || (pReqContext->CompletionStatus != NDIS_STATUS_SUCCESS))
|
|
{
|
|
TRACE1(("SyncQueryDevice error: Adapter %p, Oid %x, WokenUp %d, ComplStatus %x\n",
|
|
pAdapter, Oid, bWokenUp, pReqContext->CompletionStatus));
|
|
Status = NDIS_STATUS_DEVICE_FAILED;
|
|
break;
|
|
}
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
while (FALSE);
|
|
|
|
if (pReqContext != NULL)
|
|
{
|
|
FreeRequestContext(pAdapter, pReqContext);
|
|
}
|
|
|
|
if (pMsgFrame != NULL)
|
|
{
|
|
DereferenceMsgFrame(pMsgFrame);
|
|
}
|
|
|
|
return (Status);
|
|
|
|
}
|
|
|