mirror of https://github.com/lianthony/NT4.0
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.
4639 lines
135 KiB
4639 lines
135 KiB
// ------------------------
|
|
//
|
|
// Copyright (c) 1990 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// tpfunc.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
//
|
|
// Author:
|
|
//
|
|
// Tom Adams (tomad) 9-Jul-1991
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode, FSD
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Sanjeev Katariya (sanjeevk)
|
|
//
|
|
// 4-6-1993 Bug #5203: Changed the routine TpFuncOpenAdapter() to fill in the information
|
|
// of the media type for use by the TPCTL. This was done in order
|
|
// for TPCTL to make a decision on the OID to use when submitting
|
|
// requests to add/change mulicast addresses.
|
|
//
|
|
// 4-9-1993 Bug #5886: Changed TpFuncSendComplete() to zero out the private section of the
|
|
// NDIS_PACKET. Should the MAC access this section now after having made
|
|
// a call and to NdisSendComplete(), it will be forced to deal with
|
|
// or incorrect data
|
|
//
|
|
// 4-12-1993 Added ARCNET support
|
|
//
|
|
// Tim Wynsma (timothyw)
|
|
// 4-27-94 Added performance tests
|
|
// 5-18-94 Got rid of warnings; added some debug
|
|
// 6-08-94 Chgd perf test to client/server
|
|
//
|
|
// -----------------------------
|
|
|
|
|
|
#include <ndis.h>
|
|
|
|
#include "tpdefs.h"
|
|
#include "media.h"
|
|
#include "tpprocs.h"
|
|
#include "string.h"
|
|
|
|
|
|
VOID
|
|
TpFuncResend(POPEN_BLOCK OpenP,
|
|
PTP_REQUEST_HANDLE SendReqHndl);
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncOpenAdapter(
|
|
IN POPEN_BLOCK OpenP,
|
|
IN UCHAR OpenInstance,
|
|
IN PCMD_ARGS CmdArgs
|
|
)
|
|
|
|
// ------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine opens the request NDIS adapter and sets up the OpenBlock
|
|
// accordingly. If the call to NdisOpenAdapter does not pend, then a call
|
|
// will be made to TpFuncRequestComplete to complete the request and
|
|
// signal the application that it has finished, otherwise this call will
|
|
// be made the MAC itself once the request has finished.
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// NDIS_STATUS - This routine always returns NDIS_STATUS_PENDING as it
|
|
// will either really pend and be completed later, or we
|
|
// will fake a completion request that will complete it
|
|
// at that time.
|
|
//
|
|
// ------------------
|
|
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
NDIS_STATUS DriverStatus = NDIS_STATUS_SUCCESS;
|
|
NDIS_STATUS RequestStatus = NDIS_STATUS_SUCCESS;
|
|
STRING AdapterString;
|
|
NDIS_STRING NdisAdapterString;
|
|
NDIS_STATUS OpenErrorStatus;
|
|
UINT NameLength;
|
|
PNDIS_REQUEST Request = NULL;
|
|
PUCHAR InformationBuffer = NULL;
|
|
ULONG OidIndex;
|
|
PUCHAR p, q;
|
|
ULONG i;
|
|
PREQUEST_RESULTS OutputBuffer;
|
|
BOOLEAN GotCardAddress = FALSE;
|
|
ULONG MediaArraySize;
|
|
|
|
|
|
//
|
|
// Determine determine whether this instance of the Adapter is already
|
|
// opened.
|
|
//
|
|
|
|
if ( OpenP->OpenInstance != (UCHAR)-1 )
|
|
{
|
|
//
|
|
// If it has, then we will fail this request, and continue. We will
|
|
// not create a new Open Instance overwriting an existing one.
|
|
//
|
|
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: An open already exists for this Open Instance %d\n",
|
|
OpenInstance);
|
|
}
|
|
Status = NDIS_STATUS_OPEN_FAILED;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// First allocate the request handle and set it up as if the request
|
|
// pended. If it does not pend we will reset the flags later; before
|
|
// calling the completion routine.
|
|
//
|
|
|
|
TP_ASSERT ( OpenP->OpenReqHndl == NULL );
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&OpenP->OpenReqHndl,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncOpenAdapter: unable to allocate Request Handle.\n");
|
|
}
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( OpenP->OpenReqHndl,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
OpenP->OpenReqHndl->Signature = OPEN_REQUEST_HANDLE_SIGNATURE;
|
|
OpenP->OpenReqHndl->Open = OpenP;
|
|
OpenP->OpenReqHndl->RequestPended = FALSE;
|
|
|
|
KeInitializeEvent( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
SynchronizationEvent,
|
|
FALSE );
|
|
//
|
|
// Otherwise initialize the adapter string for the call ...
|
|
//
|
|
|
|
TP_ASSERT( OpenP->AdapterName == NULL );
|
|
|
|
NameLength = strlen( CmdArgs->ARGS.OPEN_ADAPTER.AdapterName ) + 1;
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&OpenP->AdapterName,
|
|
8 + NameLength,
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncOpenAdapter: failed to allocate adapter name buffer.\n");
|
|
}
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( OpenP->AdapterName,8 + NameLength );
|
|
}
|
|
|
|
NdisMoveMemory( OpenP->AdapterName,"\\Device\\",8 );
|
|
|
|
NdisMoveMemory( OpenP->AdapterName + 8,
|
|
CmdArgs->ARGS.OPEN_ADAPTER.AdapterName,
|
|
NameLength );
|
|
|
|
RtlInitString( &AdapterString,(PSZ)OpenP->AdapterName );
|
|
|
|
Status = RtlAnsiStringToUnicodeString( (PUNICODE_STRING)&NdisAdapterString,
|
|
(PANSI_STRING)&AdapterString,
|
|
TRUE );
|
|
|
|
TP_ASSERT( NT_SUCCESS( Status ));
|
|
|
|
//
|
|
// And make the actual NdisOpenAdapter Call.
|
|
//
|
|
|
|
if (CmdArgs->ARGS.OPEN_ADAPTER.NoArcNet) // force encapsulated ethernet
|
|
{
|
|
MediaArraySize = NDIS_MEDIUM_ARRAY_SIZE - 1;
|
|
}
|
|
else
|
|
{
|
|
MediaArraySize = NDIS_MEDIUM_ARRAY_SIZE;
|
|
}
|
|
|
|
|
|
NdisOpenAdapter(&DriverStatus,
|
|
&OpenErrorStatus,
|
|
&OpenP->NdisBindingHandle,
|
|
&OpenP->MediumIndex,
|
|
NdisMediumArray,
|
|
MediaArraySize,
|
|
OpenP->NdisProtocolHandle,
|
|
(NDIS_HANDLE)OpenP,
|
|
&NdisAdapterString,
|
|
0,
|
|
NULL );
|
|
|
|
RtlFreeUnicodeString( &NdisAdapterString );
|
|
|
|
if ( DriverStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",
|
|
TpGetStatus(Status) );
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
DriverStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( DriverStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisOpenAdapter returned %s\n",
|
|
TpGetStatus( DriverStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( DriverStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisOpenAdapter returned %s\n",
|
|
TpGetStatus( DriverStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// The open was a success, so set the open instance on
|
|
// the open block.
|
|
//
|
|
|
|
OpenP->OpenInstance = OpenInstance;
|
|
|
|
//
|
|
// and initialize the stress address depending on the medium type
|
|
// of the adapter opened.
|
|
//
|
|
|
|
switch ( NdisMediumArray[OpenP->MediumIndex] )
|
|
{
|
|
case NdisMedium802_5:
|
|
for ( i=0 ; i < ADDRESS_LENGTH ; i++ )
|
|
{
|
|
OpenP->Environment->StressAddress[i] = STRESS_FUNCTIONAL[i];
|
|
}
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
case NdisMediumDix:
|
|
case NdisMedium802_3:
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
OpenP->Environment->StressAddress[i] = STRESS_MULTICAST[i];
|
|
}
|
|
break;
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
case NdisMediumArcnet878_2:
|
|
TP_ASSERT (MediaArraySize == NDIS_MEDIUM_ARRAY_SIZE)
|
|
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
OpenP->Environment->StressAddress[i] = STRESS_ARCNET_BROADCAST[i];
|
|
}
|
|
break;
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
default:
|
|
IF_TPDBG ( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0("TpFuncOpenAdapter: Unsupported MAC Type\n");
|
|
}
|
|
DriverStatus = NDIS_STATUS_UNSUPPORTED_MEDIA;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Now allocate the Ndis Request structure to hold the query
|
|
// information requests in.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&Request,
|
|
sizeof( NDIS_REQUEST ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncOpenAdapter: unable to allocate Ndis Request buffer.\n");
|
|
}
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( Request,sizeof( NDIS_REQUEST ));
|
|
}
|
|
|
|
Request->RequestType = NdisRequestQueryInformation;
|
|
|
|
//
|
|
// Now query the card address and the maximum frame size
|
|
// from the MAC. Determine the necessary size of the
|
|
// information buffer to fit the station address, and
|
|
// allocate it.
|
|
//
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_3 )
|
|
{
|
|
OidIndex = TpLookUpOidInfo( OID_802_3_CURRENT_ADDRESS );
|
|
}
|
|
else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 )
|
|
{
|
|
OidIndex = TpLookUpOidInfo( OID_802_5_CURRENT_ADDRESS );
|
|
}
|
|
else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi )
|
|
{
|
|
OidIndex = TpLookUpOidInfo( OID_FDDI_LONG_CURRENT_ADDR );
|
|
}
|
|
else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2 )
|
|
{
|
|
OidIndex = TpLookUpOidInfo( OID_ARCNET_CURRENT_ADDRESS );
|
|
}
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&InformationBuffer,
|
|
OidArray[OidIndex].Length,
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncOpenAdapter: unable to allocate Information Buffer.\n");
|
|
}
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length);
|
|
}
|
|
|
|
Request->DATA.QUERY_INFORMATION.Oid = OidArray[OidIndex].Oid;
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length;
|
|
|
|
//
|
|
// and then make the request
|
|
//
|
|
|
|
NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request );
|
|
|
|
if ( RequestStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status );
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest Query Station Address failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest Query Station Address failed returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
GotCardAddress = TRUE;
|
|
|
|
p = OpenP->StationAddress;
|
|
q = (PUCHAR)InformationBuffer;
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
for ( i=0;i<OidArray[OidIndex].Length;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
//
|
|
// Then determine the necessary size of the information buffer
|
|
// to allocate, and allocate it.
|
|
//
|
|
|
|
OidIndex = TpLookUpOidInfo( OID_GEN_MAXIMUM_TOTAL_SIZE );
|
|
|
|
NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length );
|
|
|
|
Request->RequestType = NdisRequestQueryInformation;
|
|
|
|
Request->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length;
|
|
//
|
|
// and then make the request
|
|
//
|
|
|
|
NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request );
|
|
|
|
if ( RequestStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status );
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = TpInitMedia( OpenP,*(PULONG)InformationBuffer );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_INITIALIZE )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: TpInitMedia failed. returned %s\n",
|
|
TpGetStatus( Status ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// SANJEEVK: NEW: BUG#2930 NTRAID\NTBUG
|
|
//
|
|
|
|
//
|
|
// Set the lookahead size to the max supported by the card
|
|
// Later on if we don't like it we can change it
|
|
//
|
|
|
|
//
|
|
// QUERY the OID_GEN_MAXIMUM_LOOKAHEAD
|
|
//
|
|
OidIndex = TpLookUpOidInfo( OID_GEN_MAXIMUM_LOOKAHEAD );
|
|
|
|
NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length );
|
|
|
|
Request->RequestType = NdisRequestQueryInformation;
|
|
|
|
Request->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_LOOKAHEAD;
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length;
|
|
|
|
//
|
|
// and then make the request
|
|
//
|
|
|
|
NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request );
|
|
|
|
if ( RequestStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status );
|
|
}
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest QueryMaxLookAhead failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisRequest QueryMaxLookAhead failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// And now set the card with the maximum value
|
|
//
|
|
OidIndex = TpLookUpOidInfo( OID_GEN_CURRENT_LOOKAHEAD );
|
|
|
|
Request->RequestType = NdisRequestSetInformation;
|
|
|
|
Request->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_LOOKAHEAD;
|
|
Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length;
|
|
|
|
//
|
|
// and then make the request
|
|
//
|
|
|
|
NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request );
|
|
|
|
if ( RequestStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status );
|
|
}
|
|
goto cleanup;
|
|
}
|
|
RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest SetCurrentLookAhead to MAXLOOKAHEAD failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest SetCurrentLookAhead to MAXLOOKAHEAD failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// ENDNEW
|
|
//
|
|
|
|
//
|
|
// If we are on ethernet query the multicast list size for
|
|
// use in later tests.
|
|
//
|
|
|
|
if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_3 )
|
|
{
|
|
OidIndex = TpLookUpOidInfo( OID_802_3_MAXIMUM_LIST_SIZE );
|
|
|
|
NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length);
|
|
|
|
Request->RequestType = NdisRequestQueryInformation;
|
|
|
|
Request->DATA.QUERY_INFORMATION.Oid = OID_802_3_MAXIMUM_LIST_SIZE;
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length;
|
|
|
|
//
|
|
// and then make the request
|
|
//
|
|
|
|
NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request );
|
|
|
|
if ( RequestStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status );
|
|
}
|
|
goto cleanup;
|
|
}
|
|
RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
OpenP->Environment->MulticastListSize = *(PULONG)InformationBuffer;
|
|
}
|
|
|
|
if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi )
|
|
{
|
|
OidIndex = TpLookUpOidInfo( OID_FDDI_LONG_MAX_LIST_SIZE );
|
|
|
|
NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length);
|
|
|
|
Request->RequestType = NdisRequestQueryInformation;
|
|
|
|
Request->DATA.QUERY_INFORMATION.Oid = OID_FDDI_LONG_MAX_LIST_SIZE;
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length;
|
|
|
|
//
|
|
// and then make the request
|
|
//
|
|
|
|
NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request );
|
|
|
|
if ( RequestStatus == NDIS_STATUS_PENDING )
|
|
{
|
|
Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NT_STATUS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status );
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n",
|
|
TpGetStatus( RequestStatus ));
|
|
}
|
|
goto cleanup;
|
|
}
|
|
OpenP->Environment->MulticastListSize = *(PULONG)InformationBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
cleanup:
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress );
|
|
|
|
OutputBuffer->Signature = OPEN_RESULTS_SIGNATURE;
|
|
OutputBuffer->RequestPended = OpenP->OpenReqHndl->RequestPended;
|
|
OutputBuffer->RequestStatus = DriverStatus;
|
|
|
|
if (( Status == STATUS_SUCCESS ) &&
|
|
( DriverStatus == NDIS_STATUS_SUCCESS ))
|
|
{
|
|
OutputBuffer->OpenRequestStatus = RequestStatus;
|
|
|
|
if ( RequestStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
OutputBuffer->OID = Request->DATA.QUERY_INFORMATION.Oid;
|
|
|
|
OutputBuffer->BytesReadWritten = Request->DATA.QUERY_INFORMATION.BytesWritten;
|
|
|
|
OutputBuffer->BytesNeeded = Request->DATA.QUERY_INFORMATION.BytesNeeded;
|
|
|
|
//
|
|
// Since a portion of the call failed, i.e. one of the query
|
|
// info calls, we are failing the whole call, and need to
|
|
// reset the card open info.
|
|
//
|
|
|
|
OpenP->OpenInstance = 0xFF;
|
|
|
|
if ( OpenP->Media != NULL )
|
|
{
|
|
NdisFreeMemory( OpenP->Media,0,0 );
|
|
OpenP->Media = NULL;
|
|
}
|
|
|
|
}
|
|
else if ( GotCardAddress == TRUE )
|
|
{
|
|
PNDIS_MEDIUM MediumType = (PNDIS_MEDIUM)OutputBuffer->InformationBuffer;
|
|
//
|
|
// Sanjeevk: Bug #5203
|
|
//
|
|
// Comment
|
|
//
|
|
// This is where the user provided buffer thru the IOCTL
|
|
// is filled out with the address and the media type
|
|
//
|
|
|
|
//
|
|
// Copy the Media type into the buffer. The media type
|
|
// has been initialized by a call to TpInitMedia() earlier
|
|
// on in this function.
|
|
//
|
|
*MediumType = OpenP->Media->MediumType;
|
|
|
|
//
|
|
// Copy the adapter address into the buffer
|
|
//
|
|
p = OutputBuffer->InformationBuffer + sizeof( NDIS_MEDIUM );
|
|
q = OpenP->StationAddress;
|
|
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
OpenP->Irp->IoStatus.Status = Status;
|
|
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->OpenReqHndl != NULL )
|
|
{
|
|
NdisFreeMemory( OpenP->OpenReqHndl,0,0 );
|
|
OpenP->OpenReqHndl = NULL;
|
|
}
|
|
|
|
if ((( DriverStatus != NDIS_STATUS_SUCCESS ) ||
|
|
( RequestStatus != NDIS_STATUS_SUCCESS )) &&
|
|
( OpenP->AdapterName != NULL ))
|
|
{
|
|
|
|
NdisFreeMemory( OpenP->AdapterName,0,0 );
|
|
OpenP->AdapterName = NULL;
|
|
}
|
|
|
|
if ( Request != NULL )
|
|
{
|
|
NdisFreeMemory( Request,0,0 );
|
|
}
|
|
|
|
if ( InformationBuffer != NULL )
|
|
{
|
|
NdisFreeMemory( InformationBuffer,0,0 );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncOpenComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_STATUS OpenErrorStatus
|
|
)
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext;
|
|
ULONG NextEvent;
|
|
|
|
TP_ASSERT( OpenP != NULL );
|
|
|
|
if (( OpenP->OpenReqHndl != NULL ) &&
|
|
(( OpenP->OpenReqHndl->Signature == OPEN_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( OpenP->OpenReqHndl->Open == OpenP )))
|
|
{
|
|
IF_TPDBG(TP_DEBUG_DISPATCH)
|
|
{
|
|
TpPrint1("TpFuncOpenComplete Status = %s\n", TpGetStatus( Status ));
|
|
}
|
|
|
|
OpenP->OpenReqHndl->RequestPended = TRUE;
|
|
OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus = Status;
|
|
|
|
KeSetEvent( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,0,FALSE );
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are not expecting any Open requests to complete at this
|
|
// point, so stick this on the Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteOpen;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would have overflowed it, so
|
|
// mark the Head event overflow flag to show this.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncCloseAdapter(
|
|
IN POPEN_BLOCK OpenP
|
|
)
|
|
|
|
// --------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// ------
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
TP_ASSERT( OpenP->CloseReqHndl == NULL );
|
|
|
|
//
|
|
// First determine whether this instance of the Adapter is currently
|
|
// opened.
|
|
//
|
|
|
|
if ( OpenP->OpenInstance == (UCHAR)-1 )
|
|
{
|
|
//
|
|
// It is not already opened, so we will fail this call.
|
|
//
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint0("TpFuncCloseAdapter: An open does not exists for this Open Instance\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
return NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Otherwise allocate the request handle and set it up as if
|
|
// the request pended. If it does not pend we will reset the
|
|
// flags later before calling the completion routine.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&OpenP->CloseReqHndl,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncOpenAdapter: unable to allocate Request Handle.\n");
|
|
}
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( OpenP->CloseReqHndl,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
OpenP->CloseReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE;
|
|
OpenP->CloseReqHndl->Open = OpenP;
|
|
OpenP->CloseReqHndl->RequestPended = TRUE;
|
|
OpenP->CloseReqHndl->Irp = OpenP->Irp;
|
|
|
|
//
|
|
// Then we will attempt to close it. First set the
|
|
// open instance's closing flag to true, then signal all
|
|
// the async test protocol routines that are currently
|
|
// running to end.
|
|
//
|
|
|
|
OpenP->Closing = TRUE;
|
|
|
|
if ( OpenP->Stress->Stressing == TRUE )
|
|
{
|
|
OpenP->Stress->StopStressing = TRUE;
|
|
}
|
|
|
|
if ( OpenP->Send->Sending == TRUE )
|
|
{
|
|
OpenP->Send->StopSending = TRUE;
|
|
}
|
|
|
|
if ( OpenP->Receive->Receiving == TRUE )
|
|
{
|
|
OpenP->Receive->StopReceiving = TRUE;
|
|
}
|
|
|
|
//
|
|
// Then wait for all of the three asynchronous routines;
|
|
// STRESS, SEND and RECEIVE to finish.
|
|
//
|
|
|
|
TimeOut.HighPart = -1; // so it will be relative.
|
|
TimeOut.LowPart = (ULONG)(-(ONE_TENTH_SECOND));
|
|
|
|
while ( OpenP->ReferenceCount > 0 )
|
|
{
|
|
// Status = KeDelayExecutionThread( KernelMode,FALSE,&TimeOut );
|
|
/* NULL */ ;
|
|
}
|
|
|
|
//
|
|
// finally we will attempt to close it.
|
|
//
|
|
|
|
NdisCloseAdapter( &Status,OpenP->NdisBindingHandle );
|
|
|
|
if (( Status != NDIS_STATUS_SUCCESS ) &&
|
|
( Status != NDIS_STATUS_PENDING ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncCloseAdapter: NdisCloseAdapter returned %s\n", TpGetStatus(Status));
|
|
}
|
|
}
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
//
|
|
// If the request did not pend, we should reset the pend flag,
|
|
// and the status flag in the OpenP->CloseReqHndl, and then
|
|
// call the completion handler ourselves.
|
|
//
|
|
|
|
OpenP->CloseReqHndl->RequestPended = FALSE;
|
|
TpFuncCloseComplete( OpenP,Status );
|
|
}
|
|
}
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncCloseComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
{
|
|
POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext;
|
|
PREQUEST_RESULTS OutputBuffer;
|
|
USHORT i;
|
|
ULONG NextEvent;
|
|
|
|
TP_ASSERT( OpenP != NULL );
|
|
|
|
if (( OpenP->CloseReqHndl != NULL ) &&
|
|
(( OpenP->CloseReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( OpenP->CloseReqHndl->Open == OpenP )))
|
|
{
|
|
IF_TPDBG(TP_DEBUG_DISPATCH)
|
|
{
|
|
TpPrint1("TpFuncCloseComplete Status = %s\n", TpGetStatus( Status ));
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->CloseReqHndl->Irp != NULL )
|
|
{
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->CloseReqHndl->Irp->MdlAddress );
|
|
|
|
OutputBuffer->Signature = CLOSE_RESULTS_SIGNATURE;
|
|
OutputBuffer->RequestPended = OpenP->CloseReqHndl->RequestPended;
|
|
OutputBuffer->RequestStatus = Status;
|
|
|
|
if ( Status == NDIS_STATUS_SUCCESS )
|
|
{
|
|
//
|
|
// The close of the adapter was a success so set the flags
|
|
// in the OpenBlock back to the initial state, and reset
|
|
// the StationAddress to NULL.
|
|
//
|
|
|
|
OpenP->NdisBindingHandle = NULL;
|
|
OpenP->OpenInstance = 0xFF;
|
|
OpenP->Closing = FALSE;
|
|
|
|
if ( OpenP->AdapterName != NULL )
|
|
{
|
|
NdisFreeMemory( OpenP->AdapterName,0,0 );
|
|
OpenP->AdapterName = NULL;
|
|
}
|
|
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
OpenP->StationAddress[i] = 0x00;
|
|
}
|
|
|
|
//
|
|
// We will also free the media block at this point because
|
|
// the info it contains may not hold for the next adapter
|
|
// open on this instance.
|
|
//
|
|
|
|
if ( OpenP->Media != NULL )
|
|
{
|
|
NdisFreeMemory( OpenP->Media,0,0 );
|
|
OpenP->Media = NULL;
|
|
}
|
|
}
|
|
|
|
TP_ASSERT(Status != NDIS_STATUS_PENDING);
|
|
|
|
OpenP->CloseReqHndl->Irp->IoStatus.Status = Status;
|
|
|
|
IoMarkIrpPending( OpenP->CloseReqHndl->Irp );
|
|
|
|
IoAcquireCancelSpinLock( &OpenP->CloseReqHndl->Irp->CancelIrql );
|
|
IoSetCancelRoutine( OpenP->CloseReqHndl->Irp,NULL );
|
|
IoReleaseCancelSpinLock( OpenP->CloseReqHndl->Irp->CancelIrql );
|
|
|
|
IoCompleteRequest( OpenP->CloseReqHndl->Irp,IO_NETWORK_INCREMENT );
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
NdisFreeMemory( OpenP->CloseReqHndl,0,0 );
|
|
OpenP->CloseReqHndl = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are not expecting any requests to complete at this
|
|
// point, so stick this on the Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteClose;
|
|
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
|
|
// we should also stick some interesting info likje requesttype.
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would have overflowed it, so
|
|
// mark the Head event overflow flag to show this.
|
|
//
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncReset(
|
|
IN POPEN_BLOCK OpenP
|
|
)
|
|
|
|
// ------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// Change history:
|
|
//
|
|
// SanjeevK : During initial allocation during the reset, should the allocation fail, the spin
|
|
// lock for the OPEN_BLOCK was being acquired twice instead of being acquired
|
|
// and then released. Bug #3109
|
|
//
|
|
// ------------
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
TP_ASSERT( OpenP->ResetReqHndl == NULL );
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&OpenP->ResetReqHndl,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncReset: unable to allocate Request Handle.\n");
|
|
}
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( OpenP->ResetReqHndl,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
OpenP->ResetReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE;
|
|
OpenP->ResetReqHndl->Open = OpenP;
|
|
OpenP->ResetReqHndl->RequestPended = TRUE;
|
|
OpenP->ResetReqHndl->Irp = OpenP->Irp;
|
|
|
|
//
|
|
// Then make the call to RESET the adapter.
|
|
//
|
|
|
|
NdisReset( &Status,OpenP->NdisBindingHandle );
|
|
|
|
if (( Status != NDIS_STATUS_SUCCESS ) &&
|
|
( Status != NDIS_STATUS_PENDING ))
|
|
{
|
|
IF_TPDBG(TP_DEBUG_NDIS_ERROR)
|
|
{
|
|
TpPrint1("TpFuncReset: NdisReset failed: returned %s\n",
|
|
TpGetStatus( Status ));
|
|
}
|
|
}
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
//
|
|
// If the request did not pend, we should reset the pend flag,
|
|
// and the status flag in the RequestHandle, and call the
|
|
// completion handler ourselves.
|
|
//
|
|
|
|
OpenP->ResetReqHndl->RequestPended = FALSE;
|
|
TpFuncResetComplete( OpenP,Status );
|
|
}
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncResetComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
{
|
|
POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext;
|
|
PREQUEST_RESULTS OutputBuffer;
|
|
ULONG NextEvent;
|
|
|
|
TP_ASSERT( OpenP != NULL );
|
|
|
|
if (( OpenP->ResetReqHndl != NULL ) &&
|
|
(( OpenP->ResetReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( OpenP->ResetReqHndl->Open == OpenP )))
|
|
{
|
|
IF_TPDBG(TP_DEBUG_DISPATCH)
|
|
{
|
|
TpPrint1("TpFuncResetComplete Status = %s\n",
|
|
TpGetStatus( Status ));
|
|
}
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->ResetReqHndl->Irp != NULL )
|
|
{
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->ResetReqHndl->Irp->MdlAddress );
|
|
|
|
OutputBuffer->Signature = RESET_RESULTS_SIGNATURE;
|
|
OutputBuffer->RequestPended = OpenP->ResetReqHndl->RequestPended;
|
|
OutputBuffer->RequestStatus = Status;
|
|
|
|
OpenP->ResetReqHndl->Irp->IoStatus.Status = Status;
|
|
|
|
TP_ASSERT( Status != NDIS_STATUS_PENDING );
|
|
|
|
IoMarkIrpPending( OpenP->ResetReqHndl->Irp );
|
|
|
|
IoAcquireCancelSpinLock( &OpenP->ResetReqHndl->Irp->CancelIrql );
|
|
IoSetCancelRoutine( OpenP->ResetReqHndl->Irp,NULL );
|
|
IoReleaseCancelSpinLock( OpenP->ResetReqHndl->Irp->CancelIrql );
|
|
|
|
IoCompleteRequest( OpenP->ResetReqHndl->Irp,IO_NETWORK_INCREMENT );
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
NdisFreeMemory( OpenP->ResetReqHndl,0,0 );
|
|
OpenP->ResetReqHndl = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are not expecting any requests to complete at this
|
|
// point, so stick this on the Event Queue.
|
|
//
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteReset;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
|
|
// we should also stick some interesting info likje requesttype.
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would have overflowed it, so
|
|
// mark the Head event overflow flag to show this.
|
|
//
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncRequestQueryInfo(
|
|
IN POPEN_BLOCK OpenP,
|
|
IN PCMD_ARGS CmdArgs,
|
|
IN OUT PIRP Irp,
|
|
IN PIO_STACK_LOCATION IrpSp
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PNDIS_REQUEST Request;
|
|
PUCHAR InformationBuffer;
|
|
ULONG OidIndex;
|
|
ULONG InfoBufLength;
|
|
|
|
//
|
|
// First allocate a request handle structure to hold the
|
|
// test information in.
|
|
//
|
|
|
|
TP_ASSERT( OpenP->RequestReqHndl == NULL );
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&OpenP->RequestReqHndl,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncRequestQueryInfo: unable to allocate Request Handle.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( OpenP->RequestReqHndl,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
OpenP->RequestReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE;
|
|
OpenP->RequestReqHndl->Open = OpenP;
|
|
OpenP->RequestReqHndl->RequestPended = TRUE;
|
|
OpenP->RequestReqHndl->Irp = Irp;
|
|
|
|
OpenP->RequestReqHndl->u.INFO_REQ.IoControlCode =
|
|
IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
//
|
|
// Now allocate the Ndis Request structure to hold the
|
|
// query information request in.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&Request,
|
|
sizeof( NDIS_REQUEST ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncRequestQueryInfo: unable to allocate Request.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( Request,sizeof( NDIS_REQUEST ));
|
|
}
|
|
|
|
OpenP->RequestReqHndl->u.INFO_REQ.NdisRequestType =
|
|
Request->RequestType = NdisRequestQueryInformation;
|
|
|
|
//
|
|
// Then determine the necessary size of the information buffer
|
|
// to allocate, and allocate it.
|
|
//
|
|
|
|
OidIndex = TpLookUpOidInfo( CmdArgs->ARGS.TPQUERY.OID );
|
|
|
|
//
|
|
// If the OID we are going to call is for the Multicast List, then
|
|
// we will need a buffer of size MaxMulticastList * sizeof(Multicast)
|
|
//
|
|
|
|
if (( CmdArgs->ARGS.TPQUERY.OID == OID_802_3_MULTICAST_LIST ) ||
|
|
( CmdArgs->ARGS.TPQUERY.OID == OID_FDDI_LONG_MULTICAST_LIST ))
|
|
{
|
|
InfoBufLength = OpenP->Environment->MulticastListSize * ADDRESS_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
InfoBufLength = OidArray[OidIndex].Length;
|
|
}
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&InformationBuffer,
|
|
InfoBufLength,
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncRequestQueryInfo: unable to allocate Information Buffer.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( InformationBuffer,InfoBufLength );
|
|
}
|
|
|
|
Request->DATA.QUERY_INFORMATION.Oid = CmdArgs->ARGS.TPQUERY.OID;
|
|
Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.QUERY_INFORMATION.InformationBufferLength = InfoBufLength;
|
|
|
|
OpenP->RequestReqHndl->u.INFO_REQ.OID = CmdArgs->ARGS.TPQUERY.OID;
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBuffer = InformationBuffer;
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength = InfoBufLength;
|
|
|
|
NdisRequest( &Status,OpenP->NdisBindingHandle,Request );
|
|
|
|
if (( Status != NDIS_STATUS_SUCCESS ) &&
|
|
( Status != NDIS_STATUS_PENDING ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_NDIS_ERROR )
|
|
{
|
|
TpPrint1("TpFuncRequestQueryInfo: NdisRequest failed: returned %s\n",
|
|
TpGetStatus(Status));
|
|
}
|
|
}
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
//
|
|
// If the request did not pend, we should reset the pend flag,
|
|
// and the status flag in the OpenP->RequestReqHndl, and call the
|
|
// completion handler ourselves.
|
|
//
|
|
|
|
OpenP->RequestReqHndl->RequestPended = FALSE;
|
|
TpFuncRequestComplete( OpenP,Request,Status );
|
|
}
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncRequestSetInfo(
|
|
IN POPEN_BLOCK OpenP,
|
|
IN PCMD_ARGS CmdArgs,
|
|
IN OUT PIRP Irp,
|
|
IN PIO_STACK_LOCATION IrpSp
|
|
)
|
|
|
|
// -----------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// --------
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
PNDIS_REQUEST Request;
|
|
ULONG OidIndex;
|
|
PUCHAR InformationBuffer = NULL;
|
|
ULONG InfoBufLength = 0;
|
|
|
|
//
|
|
// First allocate a request handle structure to hold the
|
|
// test information in.
|
|
//
|
|
|
|
TP_ASSERT( OpenP->RequestReqHndl == NULL );
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&OpenP->RequestReqHndl,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncRequestSetInfo: unable to allocate Request Handle.\n");
|
|
}
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( OpenP->RequestReqHndl,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
OpenP->RequestReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE;
|
|
OpenP->RequestReqHndl->Open = OpenP;
|
|
OpenP->RequestReqHndl->RequestPended = TRUE;
|
|
OpenP->RequestReqHndl->Irp = Irp;
|
|
|
|
OpenP->RequestReqHndl->u.INFO_REQ.IoControlCode =
|
|
IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
//
|
|
// Now allocate the Ndis Request structure to hold the request
|
|
// information in.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&Request,
|
|
sizeof( NDIS_REQUEST ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncRequestSetInfo: unable to allocate Request.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( Request,sizeof( NDIS_REQUEST ));
|
|
}
|
|
|
|
Request->RequestType = OpenP->RequestReqHndl->u.INFO_REQ.NdisRequestType
|
|
= NdisRequestSetInformation;
|
|
|
|
OidIndex = TpLookUpOidInfo( CmdArgs->ARGS.TPSET.OID );
|
|
|
|
if (( CmdArgs->ARGS.TPSET.OID == OID_802_3_MULTICAST_LIST ) ||
|
|
( CmdArgs->ARGS.TPSET.OID == OID_FDDI_LONG_MULTICAST_LIST))
|
|
{
|
|
InfoBufLength = OidArray[OidIndex].Length * CmdArgs->ARGS.TPSET.NumberMultAddrs;
|
|
}
|
|
else
|
|
{
|
|
InfoBufLength = OidArray[OidIndex].Length;
|
|
}
|
|
|
|
//
|
|
// Now if the infobuffer is larger than zero bytes allocate it.
|
|
// With a multicast list size of zero we will just pass a null
|
|
// pointer.
|
|
//
|
|
|
|
if ( InfoBufLength > 0 )
|
|
{
|
|
Status = NdisAllocateMemory((PVOID *)&InformationBuffer,
|
|
InfoBufLength,
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncRequestSetInfo: unable to allocate Information Buffer.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( InformationBuffer,InfoBufLength);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now set the generic setinfo information in both the Request
|
|
// Handle, and in the SET_INFO portion of the Request struct.
|
|
//
|
|
|
|
OpenP->RequestReqHndl->u.INFO_REQ.OID = CmdArgs->ARGS.TPSET.OID;
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBuffer = InformationBuffer;
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength = InfoBufLength;
|
|
|
|
Request->DATA.SET_INFORMATION.Oid = CmdArgs->ARGS.TPSET.OID;
|
|
Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
|
|
Request->DATA.SET_INFORMATION.InformationBufferLength = InfoBufLength;
|
|
|
|
switch( CmdArgs->ARGS.TPSET.OID )
|
|
{
|
|
//
|
|
// and then add the OID specific information to the information
|
|
// section of the OVB for this request.
|
|
//
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
*((PULONG)InformationBuffer) = (ULONG)CmdArgs->ARGS.TPSET.U.PacketFilter;
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
case OID_FDDI_LONG_MULTICAST_LIST:
|
|
//
|
|
// Initialize the multicast address string to pass to the request.
|
|
//
|
|
|
|
NdisMoveMemory( InformationBuffer,
|
|
CmdArgs->ARGS.TPSET.U.MulticastAddress,
|
|
ADDRESS_LENGTH * CmdArgs->ARGS.TPSET.NumberMultAddrs );
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
case OID_802_5_CURRENT_GROUP:
|
|
//
|
|
// This is only valid if Driver Type is 802.5, should it be
|
|
// allowed if we are not working with a token ring driver ????
|
|
//
|
|
|
|
NdisMoveMemory( InformationBuffer,
|
|
&CmdArgs->ARGS.TPSET.U.FunctionalAddress,
|
|
FUNCTIONAL_ADDRESS_LENGTH );
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
*((PULONG)InformationBuffer) = (ULONG)CmdArgs->ARGS.TPSET.U.LookaheadSize;
|
|
break;
|
|
|
|
default:
|
|
IF_TPDBG(TP_DEBUG_NDIS_CALLS)
|
|
{
|
|
TpPrint0("TpFuncRequestSetInfo: invalid OID to be passed to NdisRequest\n");
|
|
}
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
Irp->IoStatus.Status = NDIS_STATUS_INVALID_OID;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_INVALID_OID;
|
|
|
|
} // switch
|
|
|
|
|
|
//
|
|
// Now that the Request is set, make the actual call.
|
|
//
|
|
|
|
NdisRequest( &Status,OpenP->NdisBindingHandle,Request );
|
|
|
|
if (( Status != NDIS_STATUS_SUCCESS ) &&
|
|
( Status != NDIS_STATUS_PENDING ))
|
|
{
|
|
IF_TPDBG(TP_DEBUG_NDIS_ERROR)
|
|
{
|
|
TpPrint1("TpFuncRequestSetInfo: NdisRequest failed: returned %s\n",
|
|
TpGetStatus(Status));
|
|
}
|
|
}
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
//
|
|
// If the request did not pend, we should reset the pend flag,
|
|
// and the status flag in the OpenP->RequestReqHndl, and call the
|
|
// completion handler ourselves.
|
|
//
|
|
|
|
OpenP->RequestReqHndl->RequestPended = FALSE;
|
|
TpFuncRequestComplete( OpenP,Request,Status );
|
|
}
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncRequestComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
{
|
|
POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext;
|
|
PREQUEST_RESULTS OutputBuffer;
|
|
ULONG NextEvent;
|
|
|
|
TP_ASSERT( OpenP != NULL );
|
|
TP_ASSERT( NdisRequest != NULL );
|
|
TP_ASSERT( Status != NDIS_STATUS_PENDING );
|
|
|
|
if (( OpenP->RequestReqHndl != NULL ) &&
|
|
(( OpenP->RequestReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( OpenP->RequestReqHndl->Open == OpenP )))
|
|
{
|
|
IF_TPDBG(TP_DEBUG_DISPATCH)
|
|
{
|
|
TpPrint2("TpFuncRequestComplete RequestType = %d, Status = %s\n",
|
|
NdisRequest->RequestType, TpGetStatus( Status));
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->Irp != NULL )
|
|
{
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->RequestReqHndl->Irp->MdlAddress );
|
|
|
|
OutputBuffer->Signature = REQUEST_RESULTS_SIGNATURE;
|
|
OutputBuffer->IoControlCode = OpenP->RequestReqHndl->u.INFO_REQ.IoControlCode;
|
|
OutputBuffer->RequestPended = OpenP->RequestReqHndl->RequestPended;
|
|
OutputBuffer->RequestStatus = Status;
|
|
|
|
TP_ASSERT( NdisRequest->RequestType ==
|
|
OpenP->RequestReqHndl->u.INFO_REQ.NdisRequestType );
|
|
|
|
OutputBuffer->NdisRequestType = NdisRequest->RequestType;
|
|
|
|
if ( NdisRequest->RequestType == NdisRequestQueryInformation )
|
|
{
|
|
TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.Oid ==
|
|
OpenP->RequestReqHndl->u.INFO_REQ.OID );
|
|
|
|
TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer ==
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBuffer );
|
|
|
|
OutputBuffer->OID = NdisRequest->DATA.QUERY_INFORMATION.Oid;
|
|
|
|
TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.BytesWritten <=
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength );
|
|
|
|
if ( Status == NDIS_STATUS_SUCCESS )
|
|
{
|
|
//
|
|
// Then we must copy the information returned into the
|
|
// OutputBuffer.
|
|
//
|
|
|
|
OutputBuffer->InformationBufferLength =
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength;
|
|
|
|
// TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength <=
|
|
// IOCTL_BUFFER_SIZE - sizeof( REQUEST_RESULTS ));
|
|
|
|
NdisMoveMemory( OutputBuffer->InformationBuffer,
|
|
(PUCHAR)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength );
|
|
}
|
|
|
|
OutputBuffer->BytesReadWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
|
|
OutputBuffer->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
|
|
}
|
|
else if ( NdisRequest->RequestType == NdisRequestSetInformation )
|
|
{
|
|
OutputBuffer->OID = OpenP->RequestReqHndl->u.INFO_REQ.OID;
|
|
|
|
TP_ASSERT( NdisRequest->DATA.SET_INFORMATION.BytesRead <=
|
|
OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength );
|
|
|
|
OutputBuffer->BytesReadWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
|
|
OutputBuffer->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
|
|
}
|
|
else
|
|
{
|
|
TP_ASSERT( FALSE );
|
|
}
|
|
|
|
//
|
|
// Now set the return status to SUCCESS and complete the request.
|
|
//
|
|
OpenP->RequestReqHndl->Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
|
|
|
|
IoMarkIrpPending( OpenP->RequestReqHndl->Irp );
|
|
|
|
IoAcquireCancelSpinLock( &OpenP->RequestReqHndl->Irp->CancelIrql );
|
|
IoSetCancelRoutine( OpenP->RequestReqHndl->Irp,NULL );
|
|
IoReleaseCancelSpinLock( OpenP->RequestReqHndl->Irp->CancelIrql );
|
|
|
|
IoCompleteRequest( OpenP->RequestReqHndl->Irp,IO_NETWORK_INCREMENT );
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// Finally free the request handle
|
|
//
|
|
|
|
if (( NdisRequest->RequestType == NdisRequestQueryInformation ) ||
|
|
( NdisRequest->RequestType == NdisRequestQueryStatistics ))
|
|
{
|
|
NdisFreeMemory( NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, 0,0 );
|
|
}
|
|
else if ( NdisRequest->RequestType == NdisRequestSetInformation )
|
|
{
|
|
if ( NdisRequest->DATA.SET_INFORMATION.InformationBufferLength > 0 )
|
|
{
|
|
NdisFreeMemory( NdisRequest->DATA.SET_INFORMATION.InformationBuffer, 0,0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TP_ASSERT( FALSE );
|
|
}
|
|
|
|
NdisFreeMemory( NdisRequest,0,0 );
|
|
NdisFreeMemory( OpenP->RequestReqHndl,0,0 );
|
|
OpenP->RequestReqHndl = NULL;
|
|
|
|
}
|
|
else if (( OpenP->OpenReqHndl != NULL ) &&
|
|
(( OpenP->OpenReqHndl->Open == OpenP ) &&
|
|
( OpenP->OpenReqHndl->Signature == OPEN_REQUEST_HANDLE_SIGNATURE )))
|
|
{
|
|
KeSetEvent( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,0,FALSE );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are not expecting any requests to complete at this
|
|
// point, so stick this on the Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteRequest;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
|
|
// we should also stick some interesting info like requesttype.
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would have overflowed it, so
|
|
// mark the Head event overflow flag to show this.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncSend(
|
|
IN POPEN_BLOCK OpenP
|
|
)
|
|
|
|
// ----------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// ---------
|
|
|
|
{
|
|
//
|
|
// Increment the reference count on the OpenBlock stating that
|
|
// an async test is running and must be ended prior to closing
|
|
// the adapter on this open. Sending of only one packet although
|
|
// handled differently still will increment the ref count.
|
|
//
|
|
|
|
TpAddReference( OpenP );
|
|
|
|
NdisZeroMemory( (PVOID)OpenP->Send->Counters,
|
|
sizeof( INSTANCE_COUNTERS ) );
|
|
|
|
//
|
|
// Initialize the SEND control flags, and reset the packet sending
|
|
// control counters.
|
|
//
|
|
|
|
OpenP->Send->Sending = TRUE;
|
|
OpenP->Send->StopSending = FALSE;
|
|
OpenP->Send->PacketsSent = 0;
|
|
OpenP->Send->PacketsPending = 0;
|
|
OpenP->Send->SendEndDpcCount = 0;
|
|
|
|
if ( OpenP->Send->NumberOfPackets == 1 )
|
|
{
|
|
//
|
|
// We are only sending one packet so just call the send
|
|
// routine, don't queue it as a DPC.
|
|
//
|
|
TpFuncSendDpc( NULL,OpenP,NULL,NULL );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We will be sending more than one packet, so queue TpFuncSendDpc
|
|
// and return Pending to the user, the DPC will send the packets,
|
|
// and after all the packets have been sent complete the request.
|
|
//
|
|
|
|
if ( !KeInsertQueueDpc( &OpenP->Send->SendDpc, NULL, NULL ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncSend failed to queue the TpFuncSendDpc.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( OpenP->Send->SendIrp != NULL )
|
|
{
|
|
OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
}
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncInitializeSendArguments(
|
|
POPEN_BLOCK OpenP,
|
|
PCMD_ARGS CmdArgs
|
|
)
|
|
|
|
// ------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine simply copies the arguments for Send into the Send
|
|
// struct on the Open Block. The send routines may then reference
|
|
// the arguments there after an asynchrnous call has returned.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// OpenP - The open block represent this open instance, the location
|
|
// where the arguments will be stored.
|
|
//
|
|
// CmdArgs - The arguments passed in from the app for this test run.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None - the Send arguments are copied to the Open Block.
|
|
//
|
|
// -------------
|
|
|
|
{
|
|
PUCHAR p, q, s, t;
|
|
ULONG i;
|
|
|
|
OpenP->Send->NumberOfPackets = CmdArgs->ARGS.TPSEND.NumberOfPackets;
|
|
|
|
if ( CmdArgs->ARGS.TPSEND.PacketSize > OpenP->Media->MaxPacketLen )
|
|
{
|
|
OpenP->Send->PacketSize = OpenP->Media->MaxPacketLen;
|
|
IF_TPDBG ( TP_DEBUG_IOCTL_ARGS )
|
|
{
|
|
TpPrint1("TpFuncInitializeSendArguments: Invalid PacketSize; using %d\n",
|
|
OpenP->Send->PacketSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OpenP->Send->PacketSize = CmdArgs->ARGS.TPSEND.PacketSize;
|
|
}
|
|
|
|
p = OpenP->Send->DestAddress;
|
|
q = CmdArgs->ARGS.TPSEND.DestAddress;
|
|
s = OpenP->Send->ResendAddress;
|
|
t = CmdArgs->ARGS.TPSEND.ResendAddress;
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
*s++ = *t++;
|
|
}
|
|
|
|
if (OpenP->Send->PacketSize < (sizeof(FUNC2_PACKET) + 4))
|
|
{
|
|
OpenP->Send->ResendPackets = FALSE;
|
|
}
|
|
|
|
else if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 )
|
|
{
|
|
//
|
|
// Since there is no concept of a NULL address we have no choice but
|
|
// to always use a resend address
|
|
// Addresses in arcnet range from 0x00 to 0xff where 0x00 is a broadcast
|
|
// address
|
|
//
|
|
OpenP->Send->ResendPackets = TRUE;
|
|
}
|
|
|
|
else
|
|
{
|
|
if ( RtlCompareMemory( OpenP->Send->ResendAddress,
|
|
NULL_ADDRESS,
|
|
OpenP->Media->AddressLen ) != OpenP->Media->AddressLen )
|
|
{
|
|
OpenP->Send->ResendPackets = TRUE;
|
|
}
|
|
else
|
|
{
|
|
OpenP->Send->ResendPackets = FALSE;
|
|
}
|
|
}
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncSendDpc(
|
|
IN PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SysArg1,
|
|
IN PVOID SysArg2
|
|
)
|
|
|
|
// -------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// -----------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
|
|
PTP_REQUEST_HANDLE RequestHandle;
|
|
NDIS_STATUS Status;
|
|
PNDIS_PACKET Packet;
|
|
LARGE_INTEGER DueTime;
|
|
PPROTOCOL_RESERVED ProtRes;
|
|
|
|
UNREFERENCED_PARAMETER( Dpc );
|
|
UNREFERENCED_PARAMETER( SysArg1 );
|
|
UNREFERENCED_PARAMETER( SysArg2 );
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&RequestHandle,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG (TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncSendDpc: unable to allocate Request Handle.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Send->SendIrp != NULL )
|
|
{
|
|
OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
TpFuncSendEndDpc( NULL,OpenP,NULL,NULL );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
RequestHandle->Signature = SEND_REQUEST_HANDLE_SIGNATURE;
|
|
RequestHandle->Open = OpenP;
|
|
RequestHandle->RequestPended = TRUE;
|
|
RequestHandle->Irp = OpenP->Send->SendIrp;
|
|
|
|
Packet = TpFuncAllocateSendPacket( OpenP );
|
|
|
|
if ( Packet == NULL )
|
|
{
|
|
IF_TPDBG( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0("TpFuncSendDpc: Unable to create a Send packet\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if ( OpenP->Send->SendIrp != NULL )
|
|
{
|
|
OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
TpFuncSendEndDpc( NULL,OpenP,NULL,NULL );
|
|
return;
|
|
}
|
|
|
|
RequestHandle->u.SEND_REQ.Packet = Packet;
|
|
RequestHandle->u.SEND_REQ.PacketSize = OpenP->Send->PacketSize;
|
|
RequestHandle->u.SEND_REQ.SendPacket = TRUE;
|
|
|
|
ProtRes = PROT_RES( Packet );
|
|
ProtRes->RequestHandle = RequestHandle;
|
|
|
|
//
|
|
// Set the check sum in the PROTOCOL RESERVED Section of the
|
|
// packet header to ensure it is not touched while the packet
|
|
// is in the hands of the MAC.
|
|
//
|
|
|
|
ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) );
|
|
++OpenP->Send->PacketsPending;
|
|
++OpenP->Send->Counters->Sends;
|
|
|
|
NdisSend( &Status,OpenP->NdisBindingHandle,Packet );
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
--OpenP->Send->PacketsPending;
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
//
|
|
// If we are running on TokenRing the following to "failures"
|
|
// are not considered failures NDIS_STATUS_NOT_RECOGNIZED -
|
|
// no one on the ring recognized the address as theirs, or
|
|
// NDIS_STATUS_NOT_COPIED - no one on the ring copied the
|
|
// packet, so we need to special case this and not count
|
|
// these as failures.
|
|
//
|
|
// SanjeevK : Even FDDI returns the same errors as 802.5
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) )
|
|
{
|
|
if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) &&
|
|
( Status != NDIS_STATUS_NOT_COPIED ))
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
TpPrint1("Send failed: status = %s", TpGetStatus(Status));
|
|
}
|
|
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
}
|
|
|
|
RequestHandle->RequestPended = FALSE;
|
|
|
|
TpFuncSendComplete( OpenP,Packet,Status );
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Send->Counters->SendPends;
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ((( OpenP->Send->SendIrp != NULL ) &&
|
|
( OpenP->Send->SendIrp->Cancel == FALSE )) &&
|
|
(( ++OpenP->Send->PacketsSent < OpenP->Send->NumberOfPackets ) &&
|
|
( OpenP->Send->StopSending == FALSE )))
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
DueTime.HighPart = -1; // So it will be relative.
|
|
DueTime.LowPart = (ULONG)(-4 * (ONE_HUNDREDTH_SECOND));
|
|
|
|
if ( KeSetTimer(&OpenP->Send->SendTimer,
|
|
DueTime,
|
|
&OpenP->Send->SendDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncSendDpc set SendTimer while timer existed.\n");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
DueTime.HighPart = 0xFFFFFFFF; // So it will be relative.
|
|
DueTime.LowPart = (ULONG)(-(ONE_SECOND));
|
|
|
|
if ( KeSetTimer(&OpenP->Send->SendTimer,
|
|
DueTime,
|
|
&OpenP->Send->SendEndDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncSendDpc set SendTimer while timer existed(2).\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncSendEndDpc(
|
|
IN PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SysArg1,
|
|
IN PVOID SysArg2
|
|
)
|
|
|
|
// -------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// ------------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
|
|
LARGE_INTEGER DueTime;
|
|
|
|
UNREFERENCED_PARAMETER( Dpc );
|
|
UNREFERENCED_PARAMETER( SysArg1 );
|
|
UNREFERENCED_PARAMETER( SysArg2 );
|
|
|
|
//
|
|
// See if we have any outstanding packets left to complete. If we do,
|
|
// then we will reset the time to queue this dpc routine again in one
|
|
// second, if after ten requeue the packet has still no completed we
|
|
// assume it will never complete and return the results and finish.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ((( OpenP->Send->SendIrp != NULL ) &&
|
|
( OpenP->Send->SendIrp->Cancel == FALSE )) &&
|
|
(( OpenP->Send->PacketsPending != 0 ) &&
|
|
( OpenP->Send->SendEndDpcCount++ < 10 )))
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
DueTime.HighPart = -1; // So it will be relative.
|
|
DueTime.LowPart = (ULONG)(-(ONE_SECOND));
|
|
|
|
if ( KeSetTimer(&OpenP->Send->SendTimer,
|
|
DueTime,
|
|
&OpenP->Send->SendEndDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncSendEndDpc set SendTimer while timer existed.\n");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Write the statistics to the send results outputbuffer.
|
|
//
|
|
|
|
if (( OpenP->Send->SendIrp != NULL ) &&
|
|
( OpenP->Send->SendIrp->Cancel == FALSE ))
|
|
{
|
|
TpWriteSendReceiveResults( OpenP->Send->Counters,
|
|
OpenP->Send->SendIrp );
|
|
}
|
|
|
|
//
|
|
// and if the IoStatus.Status has not been set, then set it.
|
|
//
|
|
|
|
if ( (OpenP->Send->SendIrp != NULL) &&
|
|
(OpenP->Send->SendIrp->IoStatus.Status == NDIS_STATUS_PENDING ))
|
|
{
|
|
OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// Now set the sending flag to indicate that we are no longer
|
|
// SENDing packets.
|
|
//
|
|
|
|
OpenP->Send->Sending = FALSE;
|
|
|
|
//
|
|
// and decrement the reference count on the OpenBlock stating this
|
|
// instance of an async test is no longer running, and the adapter
|
|
// may be closed if requested.
|
|
//
|
|
|
|
|
|
if (OpenP->Send->SendIrp != NULL)
|
|
{
|
|
TpRemoveReference( OpenP );
|
|
IoMarkIrpPending( OpenP->Send->SendIrp );
|
|
|
|
IoAcquireCancelSpinLock( &OpenP->Send->SendIrp->CancelIrql );
|
|
IoSetCancelRoutine( OpenP->Send->SendIrp,NULL );
|
|
IoReleaseCancelSpinLock( OpenP->Send->SendIrp->CancelIrql );
|
|
|
|
IoCompleteRequest( OpenP->Send->SendIrp,IO_NETWORK_INCREMENT );
|
|
|
|
OpenP->Send->SendIrp = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncSendComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_PACKET Packet,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
|
|
// ---------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// --------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
PPROTOCOL_RESERVED ProtRes;
|
|
PTP_REQUEST_HANDLE SendReqHndl;
|
|
PNDIS_BUFFER Buffer;
|
|
ULONG NextEvent;
|
|
|
|
TP_ASSERT( Packet != NULL );
|
|
|
|
//
|
|
// Zero out the private section reserved for the MAC out of the NDIS packet
|
|
//
|
|
RtlZeroMemory( (PVOID)Packet->MacReserved, sizeof( Packet->MacReserved ) );
|
|
|
|
ProtRes = PROT_RES( Packet );
|
|
SendReqHndl = ProtRes->RequestHandle;
|
|
|
|
TP_ASSERT( Packet == SendReqHndl->u.SEND_REQ.Packet );
|
|
|
|
//
|
|
// Where did this packet originate from ?
|
|
//
|
|
|
|
if (( SendReqHndl->Signature == SEND_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( SendReqHndl->u.SEND_REQ.SendPacket == TRUE ))
|
|
{
|
|
//
|
|
// If the packet was sent by the SEND command, then decrement the
|
|
// counter tracking the number of outstanding functional packets,
|
|
// and if the send succeeded increment the completion counter.
|
|
//
|
|
|
|
if ( SendReqHndl->RequestPended )
|
|
{
|
|
--OpenP->Send->PacketsPending;
|
|
|
|
++OpenP->Send->Counters->SendComps;
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
//
|
|
// If we are running on TokenRing the following to "failures"
|
|
// are not considered failures NDIS_STATUS_NOT_RECOGNIZED -
|
|
// no one on the ring recognized the address as theirs, or
|
|
// NDIS_STATUS_NOT_COPIED - no one on the ring copied the
|
|
// packet, so we need to special case this and not count
|
|
// these as failures.
|
|
//
|
|
// SanjeevK : Even FDDI returns the same errors as 802.5
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) )
|
|
{
|
|
if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) &&
|
|
( Status != NDIS_STATUS_NOT_COPIED ))
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
TpPrint1("Send failed: status = %s", TpGetStatus(Status));
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// also check that the PROTOCOL_RESERVED section of the packet
|
|
// header was not touched.
|
|
//
|
|
|
|
if ( !TpCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ),
|
|
&ProtRes->CheckSum ))
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
TP_ASSERT( FALSE );
|
|
}
|
|
|
|
//
|
|
// then break the packet down and release its memory.
|
|
//
|
|
|
|
TpFuncFreePacket( SendReqHndl->u.SEND_REQ.Packet,SendReqHndl->u.SEND_REQ.PacketSize );
|
|
|
|
NdisFreeMemory( SendReqHndl,0,0 );
|
|
|
|
}
|
|
else if (( SendReqHndl->Signature == SEND_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( SendReqHndl->u.SEND_REQ.SendPacket == FALSE ))
|
|
{
|
|
//
|
|
// This packet was sent by an invocation of the RECEIVE command from
|
|
// TpFuncReceive when a RESEND packet was received.
|
|
//
|
|
|
|
if ( SendReqHndl->RequestPended )
|
|
{
|
|
--OpenP->Receive->PacketsPending;
|
|
|
|
++OpenP->Receive->Counters->SendComps;
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
//
|
|
// If we are running on TokenRing the following to "failures"
|
|
// are not considered failures NDIS_STATUS_NOT_RECOGNIZED -
|
|
// no one on the ring recognized the address as theirs, or
|
|
// NDIS_STATUS_NOT_COPIED - no one on the ring copied the
|
|
// packet, so we need to special case this and not count
|
|
// these as failures.
|
|
//
|
|
// SanjeevK : Even FDDI returns the same errors as 802.5
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
|
|
if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) )
|
|
{
|
|
if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) &&
|
|
( Status != NDIS_STATUS_NOT_COPIED ))
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// also check that the PROTOCOL_RESERVED section of the packet
|
|
// header was not touched.
|
|
//
|
|
|
|
if ( !TpCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ),
|
|
&ProtRes->CheckSum ))
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
TP_ASSERT( FALSE );
|
|
}
|
|
|
|
//
|
|
// then break the packet down and release its memory.
|
|
//
|
|
|
|
NdisUnchainBufferAtFront( Packet,&Buffer );
|
|
NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 );
|
|
TpFreeBuffer( Buffer );
|
|
NdisFreePacket( Packet );
|
|
NdisFreeMemory( SendReqHndl,0,0 );
|
|
|
|
}
|
|
else if ( SendReqHndl->Signature == GO_REQUEST_HANDLE_SIGNATURE )
|
|
{
|
|
//
|
|
// check that the PROTOCOL_RESERVED section of the packet
|
|
// header was not touched.
|
|
//
|
|
|
|
// This is just a go packet, check that the PROTOCOL_RESERVED
|
|
// section of the packet header was not touched, then break
|
|
// the packet down and release its memory.
|
|
//
|
|
|
|
if ( !TpCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ),
|
|
&ProtRes->CheckSum ))
|
|
{
|
|
TP_ASSERT( FALSE );
|
|
}
|
|
|
|
NdisUnchainBufferAtFront( Packet,&Buffer );
|
|
NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 );
|
|
TpFreeBuffer( Buffer );
|
|
NdisFreePacket( Packet );
|
|
NdisFreeMemory( SendReqHndl,0,0 );
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// An unexpected call to the send completion routine has been made.
|
|
// Since we are not expecting it, stick the information on the
|
|
// Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteSend;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would overflow it.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncInitializeReceive(
|
|
IN POPEN_BLOCK OpenP
|
|
)
|
|
|
|
// ---------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// -------
|
|
|
|
{
|
|
LARGE_INTEGER DueTime;
|
|
|
|
NdisZeroMemory( (PVOID)OpenP->Receive->Counters,
|
|
sizeof( INSTANCE_COUNTERS ) );
|
|
|
|
//
|
|
// Initialize the RECEIVE control flags, and reset the packet
|
|
// sending control counters.
|
|
//
|
|
|
|
OpenP->Receive->Receiving = TRUE;
|
|
OpenP->Receive->StopReceiving = FALSE;
|
|
OpenP->Receive->PacketsPending = 0;
|
|
OpenP->Receive->ReceiveEndDpcCount = 0;
|
|
|
|
//
|
|
// The zero out the receive counters.
|
|
//
|
|
|
|
NdisZeroMemory( (PVOID)OpenP->Receive->Counters,
|
|
sizeof( INSTANCE_COUNTERS ) );
|
|
|
|
//
|
|
// Initialize the DPCs used to call ReceiveDpc and ReceiveEndDpc.
|
|
//
|
|
|
|
KeInitializeDpc(&OpenP->Receive->ReceiveDpc,
|
|
TpFuncReceiveDpc,
|
|
(PVOID)OpenP );
|
|
|
|
KeInitializeDpc(&OpenP->Receive->ReceiveEndDpc,
|
|
TpFuncReceiveEndDpc,
|
|
(PVOID)OpenP );
|
|
|
|
//
|
|
// And finally set the timer for the ReceiveDpc to queue the
|
|
// routine later.
|
|
//
|
|
|
|
DueTime.HighPart = 0xFFFFFFFF; // So it will be relative.
|
|
DueTime.LowPart = (ULONG)(-(ONE_SECOND));
|
|
|
|
if ( KeSetTimer(&OpenP->Receive->ReceiveTimer,
|
|
DueTime,
|
|
&OpenP->Receive->ReceiveDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncReceiveDpc set Receive timer while timer existed.\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Increment the reference count on the OpenBlock stating that
|
|
// an async test is running and must be ended prior to closing
|
|
// the adapter on this open.
|
|
//
|
|
|
|
TpAddReference( OpenP );
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncReceive(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_HANDLE MacReceiveContext,
|
|
IN PVOID HeaderBuffer,
|
|
IN UINT HeaderBufferSize,
|
|
IN PVOID LookaheadBuffer,
|
|
IN UINT LookaheadBufferSize,
|
|
IN UINT PacketSize
|
|
)
|
|
|
|
// -------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// -----------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PPACKET_INFO PacketInfo;
|
|
PTP_REQUEST_HANDLE RequestHandle;
|
|
PGO_PACKET_INFO GoPacketInfo;
|
|
PUCHAR Memory;
|
|
PUCHAR SrcAddr;
|
|
PNDIS_PACKET Packet;
|
|
PNDIS_BUFFER Buffer;
|
|
PPROTOCOL_RESERVED ProtRes;
|
|
UINT BytesTransferred;
|
|
UINT HeaderVariance = sizeof(MEDIA_HEADER)-HeaderBufferSize;
|
|
ULONG DataSize;
|
|
ULONG NextEvent;
|
|
ULONG i;
|
|
|
|
//
|
|
// The LookAhead Buffer has been adjusted to point to the beggining of the
|
|
// PACKET_INFO structure
|
|
//
|
|
PacketInfo = (PPACKET_INFO)LookaheadBuffer;
|
|
|
|
//
|
|
// Are we expecting to receive a packet at this time, and is this
|
|
// packet large enough to be a functional send packet, and is the
|
|
// signature in the packet header correct?
|
|
//
|
|
|
|
if ((( OpenP->Receive->Receiving == TRUE ) &&
|
|
( PacketSize >= sizeof( PACKET_INFO ))) &&
|
|
(( PacketInfo->Signature == FUNC1_PACKET_SIGNATURE ) ||
|
|
( PacketInfo->Signature == FUNC2_PACKET_SIGNATURE )))
|
|
{
|
|
if ( OpenP->Receive->StopReceiving == TRUE )
|
|
{
|
|
//
|
|
// The receive test is shutting down, so just count the packet.
|
|
//
|
|
|
|
++OpenP->Receive->Counters->Receives;
|
|
|
|
if ( !TpCheckSum( (PUCHAR)PacketInfo,
|
|
sizeof( PACKET_INFO ) - sizeof( ULONG ),
|
|
(PULONG)&PacketInfo->CheckSum ))
|
|
{
|
|
++OpenP->Receive->Counters->CorruptRecs;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are in the normal receiving mode, and have a good
|
|
// packet, so we will handle it as requested.
|
|
//
|
|
|
|
++OpenP->Receive->Counters->Receives;
|
|
|
|
if ( !TpCheckSum( (PUCHAR)PacketInfo,
|
|
sizeof( PACKET_INFO ) - sizeof( ULONG ),
|
|
(PULONG)&PacketInfo->CheckSum ))
|
|
{
|
|
++OpenP->Receive->Counters->CorruptRecs;
|
|
return NDIS_STATUS_NOT_RECOGNIZED;
|
|
}
|
|
|
|
//
|
|
// Is there any thing in the packet other than the header??
|
|
//
|
|
|
|
//
|
|
// STARTCHANGE
|
|
// Please note that this packet size is NOT the PacketSize which
|
|
// we receive in the TestProtocolReceive but is
|
|
//
|
|
// PacketSize we get with IndicateReceive + the size of the header
|
|
// = TRUE PACKET SIZE
|
|
//
|
|
DataSize = ((PPACKET_INFO)LookaheadBuffer)->PacketSize -
|
|
( sizeof( PACKET_INFO ) + sizeof( MEDIA_HEADER ) );
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
if ( DataSize > 0 )
|
|
{
|
|
SrcAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->SrcAddrOffset;
|
|
OpenP->Receive->ResendType =
|
|
( RtlCompareMemory(SrcAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen) == OpenP->Media->AddressLen);
|
|
|
|
//
|
|
// Allocate the request handle and set it up as if the request
|
|
// pended. If it does not pend we will reset the flags later before
|
|
// calling the completion routine.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&RequestHandle,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0("TpFuncReceive: unable to allocated request handle.\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if (OpenP->Receive->ReceiveIrp != NULL )
|
|
{
|
|
OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
RequestHandle->Signature = FUNC_REQUEST_HANDLE_SIGNATURE;
|
|
RequestHandle->Open = OpenP;
|
|
RequestHandle->RequestPended = TRUE;
|
|
RequestHandle->u.TRANS_REQ.DataSize = DataSize;
|
|
|
|
//
|
|
// Now allocate the memory to copy the packet data into.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&Memory,
|
|
DataSize,
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG(TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncReceive: unable to allocate resend buffer memory.\n");
|
|
}
|
|
NdisFreeMemory( RequestHandle,0,0 );
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if (OpenP->Receive->ReceiveIrp != NULL )
|
|
{
|
|
OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( Memory,DataSize );
|
|
}
|
|
|
|
//
|
|
// Then allocate the buffer that will reference the memory,
|
|
//
|
|
|
|
Buffer = IoAllocateMdl( Memory,
|
|
DataSize,
|
|
TRUE,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if ( Buffer == NULL )
|
|
{
|
|
IF_TPDBG(TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncReceive: unable to allocate resend mdl buffer\n");
|
|
}
|
|
NdisFreeMemory( Memory,0,0 );
|
|
NdisFreeMemory( RequestHandle,0,0 );
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if (OpenP->Receive->ReceiveIrp != NULL )
|
|
{
|
|
OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
MmBuildMdlForNonPagedPool( (PMDL)Buffer );
|
|
|
|
//
|
|
// and finally the NDIS_PACKET to pass to the NdisTransferData call.
|
|
//
|
|
|
|
NdisAllocatePacket( &Status,
|
|
&Packet,
|
|
OpenP->Receive->PacketHandle );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG(TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncReceive: unable to allocate resend packet\n");
|
|
}
|
|
IoFreeMdl( Buffer );
|
|
NdisFreeMemory( Memory,0,0 );
|
|
NdisFreeMemory( RequestHandle,0,0 );
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
if (OpenP->Receive->ReceiveIrp != NULL )
|
|
{
|
|
OpenP->Receive->ReceiveIrp->IoStatus.Status = Status;
|
|
}
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
return Status;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Setup the protocol reserved portion of the packet so the
|
|
// completion routines know what and where to deallocate.
|
|
//
|
|
|
|
ProtRes = PROT_RES( Packet );
|
|
ProtRes->Pool.PacketHandle = OpenP->Receive->PacketHandle;
|
|
ProtRes->InstanceCounters = OpenP->Receive->Counters;
|
|
ProtRes->RequestHandle = RequestHandle;
|
|
|
|
ProtRes->CheckSum =
|
|
TpSetCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) );
|
|
|
|
//
|
|
// reference the packet in the request handle.
|
|
//
|
|
|
|
RequestHandle->u.TRANS_REQ.Packet = Packet;
|
|
}
|
|
|
|
//
|
|
// Now chain the buffer to the packet.
|
|
//
|
|
|
|
NdisChainBufferAtFront( Packet,Buffer );
|
|
|
|
//
|
|
// And transfer the data into the newly created packet.
|
|
//
|
|
|
|
++OpenP->Receive->Counters->XferData;
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
NdisTransferData( &Status,
|
|
OpenP->NdisBindingHandle,
|
|
MacReceiveContext,
|
|
(sizeof(PACKET_INFO)+HeaderVariance),
|
|
DataSize,
|
|
Packet,
|
|
&BytesTransferred );
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
if ( Status == NDIS_STATUS_PENDING )
|
|
{
|
|
//
|
|
// The deallocation of resources and any resending will
|
|
// be handled by the completion routine, so just count
|
|
// the transfer pending and split.
|
|
//
|
|
++OpenP->Receive->Counters->XferDataPends;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the request did not pend, we should reset the
|
|
// pend flag, and the status flag in the RequestHandle,
|
|
// and then call the completion handler ourselves.
|
|
//
|
|
|
|
RequestHandle->RequestPended = FALSE;
|
|
|
|
TpFuncTransferDataComplete( OpenP,
|
|
Packet,
|
|
Status,
|
|
BytesTransferred );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TpPrint2("Full packetsize = %d, true packetsize = %d\n",
|
|
((PPACKET_INFO)LookaheadBuffer)->PacketSize, DataSize);
|
|
TpBreakPoint();
|
|
}
|
|
}
|
|
}
|
|
else if (( PacketSize >= sizeof( GO_PACKET_INFO )) &&
|
|
( PacketInfo->Signature == GO_PACKET_SIGNATURE ))
|
|
{
|
|
GoPacketInfo = (PGO_PACKET_INFO)LookaheadBuffer;
|
|
SrcAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->SrcAddrOffset;
|
|
|
|
if ( !TpCheckSum( (PUCHAR)GoPacketInfo,
|
|
sizeof( GO_PACKET_INFO ) - sizeof( ULONG ),
|
|
(PULONG)&GoPacketInfo->CheckSum ))
|
|
{
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
}
|
|
else
|
|
{
|
|
NdisAcquireSpinLock( &OpenP->Pause->SpinLock );
|
|
|
|
if ((( OpenP->Pause->GoReceived == TRUE ) ||
|
|
|
|
//
|
|
// We have not finished processing the last GO packet,
|
|
// and a new one has arrived. We can't accept it until
|
|
// the last GO has been handled. We will ignore this
|
|
// packet.
|
|
//
|
|
|
|
((( GoPacketInfo->PacketType == TP_GO ) &&
|
|
( GoPacketInfo->TestSignature == OpenP->Pause->TestSignature )) &&
|
|
( GoPacketInfo->UniqueSignature == OpenP->Pause->UniqueSignature ))) ||
|
|
|
|
//
|
|
// Or we have finished handling the last GO packet, and
|
|
// received another one for the same PAUSE before the
|
|
// GO sender received and handled the GO_ACK packet.
|
|
// We will ignore this packet also.
|
|
//
|
|
|
|
( RtlCompareMemory( SrcAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen) == OpenP->Media->AddressLen ))
|
|
{
|
|
|
|
//
|
|
// Or this packet was sent by us, not another protocol
|
|
// on another machine, must have the packet filter set
|
|
// to promiscuous mode, ignore this packet also.
|
|
//
|
|
|
|
NdisReleaseSpinLock( &OpenP->Pause->SpinLock );
|
|
}
|
|
else
|
|
{
|
|
OpenP->Pause->GoReceived = TRUE;
|
|
|
|
switch ( OpenP->Media->MediumType )
|
|
{
|
|
case NdisMediumArcnet878_2:
|
|
case NdisMediumFddi :
|
|
case NdisMediumDix :
|
|
case NdisMedium802_3 :
|
|
case NdisMedium802_5 :
|
|
for ( i=0 ; i < OpenP->Media->AddressLen; i++ )
|
|
{
|
|
OpenP->Pause->RemoteAddress[i] = (CHAR)&SrcAddr[i];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
IF_TPDBG ( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0("TpFuncReceive: Unsupported MAC Media Type\n");
|
|
}
|
|
}
|
|
|
|
OpenP->Pause->TestSignature = GoPacketInfo->TestSignature;
|
|
OpenP->Pause->UniqueSignature = GoPacketInfo->UniqueSignature;
|
|
OpenP->Pause->PacketType = GoPacketInfo->PacketType;
|
|
|
|
NdisReleaseSpinLock( &OpenP->Pause->SpinLock );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// TEMP -- Find out WHY we got here...
|
|
|
|
// this one is valid--can get it during abort of performance test
|
|
// if ( OpenP->Receive->Receiving != TRUE )
|
|
// {
|
|
// TpPrint0("Rcv--receiving == FALSE\n");
|
|
// }
|
|
|
|
if ( PacketSize >= sizeof( PACKET_INFO ))
|
|
{
|
|
TpPrint1("Rcv--Psize >= PACKET_INFO, signature = %x\n", PacketInfo->Signature);
|
|
}
|
|
else if ( PacketSize >= sizeof( GO_PACKET_INFO ))
|
|
{
|
|
TpPrint1("Rcv--Psize >= GO_PACKET_INFO, signature = %x\n", PacketInfo->Signature);
|
|
}
|
|
else
|
|
{
|
|
TpPrint0("Rcv--Psize < GO_PACKET_INFO\n");
|
|
}
|
|
// TpBreakPoint();
|
|
|
|
//
|
|
//
|
|
// We are not expecting to receive packets, or this packet is not
|
|
// large enough to be a functional packet, or we are not expecting
|
|
// to receive this packet. so stick it on the Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateReceive;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
|
|
//
|
|
// XXX: At this point we could stick the first X bytes (header)
|
|
// into the Events[head].EventInfo using xferdata.
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would have overflowed it, so
|
|
// mark the Head event overflow flag to show this.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
++OpenP->EventQueue->ReceiveIndicationCount;
|
|
OpenP->EventQueue->ExpectReceiveComplete = TRUE;
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncReceiveComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext
|
|
)
|
|
|
|
// -------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// -----
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
|
|
if ( OpenP->Receive->Receiving == TRUE )
|
|
{
|
|
++OpenP->Receive->Counters->ReceiveComps;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are not expecting this completion, so stick the
|
|
// info on the event queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
//****************************************************************
|
|
//
|
|
// NOTE: Due to the fact that a MAC will complete all receive
|
|
// indications to EVERY transport that has it opened this
|
|
// completion is not entirely unexpected, and therefore will
|
|
// not be added to the Event Queue.
|
|
//
|
|
//****************************************************************
|
|
|
|
#if 0
|
|
//
|
|
// We have received an unexpected Status Indication, so
|
|
// we are expecting (???) to receive the completion.
|
|
//
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateReceiveComplete;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
|
|
// XXX: Was it expected ???
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would overflow it.
|
|
//
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Reset the status indication counter to zero, and set the
|
|
// status completion expected flag to show that no completion
|
|
// routine is expected.
|
|
//
|
|
|
|
OpenP->EventQueue->ReceiveIndicationCount = 0;
|
|
OpenP->EventQueue->ExpectReceiveComplete = FALSE;
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncTransferDataComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_PACKET Packet,
|
|
IN NDIS_STATUS Status,
|
|
IN UINT BytesTransferred
|
|
)
|
|
|
|
// ----------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// ---------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
PNDIS_BUFFER Buffer;
|
|
PPROTOCOL_RESERVED ProtRes;
|
|
PTP_REQUEST_HANDLE XferReqHndl;
|
|
PTP_REQUEST_HANDLE SendReqHndl;
|
|
PTP_PACKET TpPacket;
|
|
PUCHAR BufMem;
|
|
// NDIS_STATUS SendStatus;
|
|
ULONG NextEvent;
|
|
ULONG i;
|
|
LARGE_INTEGER DueTime;
|
|
|
|
|
|
TP_ASSERT( Packet != NULL );
|
|
|
|
ProtRes = PROT_RES( Packet );
|
|
XferReqHndl = ProtRes->RequestHandle;
|
|
|
|
TP_ASSERT( Status == NDIS_STATUS_SUCCESS );
|
|
TP_ASSERT( Packet == XferReqHndl->u.TRANS_REQ.Packet );
|
|
|
|
//
|
|
// Are we expecting to complete a Transfer Data at this time?
|
|
// First determine if we are running a RECEIVE test. If so,
|
|
// determine whether this is a legitimate completion, or a
|
|
// bug.
|
|
//
|
|
|
|
TP_ASSERT( OpenP != NULL );
|
|
|
|
if (( OpenP->Receive->StopReceiving == FALSE ) &&
|
|
(( XferReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) &&
|
|
( XferReqHndl->Open == (POPEN_BLOCK)ProtocolBindingContext )))
|
|
{
|
|
//
|
|
// If so then verfiy the PROTOCOL RESERVED section of the
|
|
// packet was not touched.
|
|
//
|
|
|
|
if ( !TpCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ),
|
|
&ProtRes->CheckSum ))
|
|
{
|
|
++OpenP->Receive->Counters->XferDataFails;
|
|
return;
|
|
}
|
|
|
|
//
|
|
// and then grab the pointer to the newly transferred packet,
|
|
// and the data stored in it.
|
|
//
|
|
|
|
NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL );
|
|
|
|
TpPacket = (PTP_PACKET)MmGetMdlVirtualAddress( Buffer );
|
|
|
|
TP_ASSERT( BytesTransferred == XferReqHndl->u.TRANS_REQ.DataSize );
|
|
|
|
//
|
|
// We are expecting it, so if the request truly pended, then
|
|
// count the completion now.
|
|
//
|
|
|
|
if ( XferReqHndl->RequestPended == TRUE )
|
|
{
|
|
++OpenP->Receive->Counters->XferDataComps;
|
|
}
|
|
|
|
//
|
|
// We have a Func Packet, is it a resend packet or not?
|
|
//
|
|
|
|
if (( TpPacket->u.F1.info.Signature == FUNC2_PACKET_SIGNATURE ) &&
|
|
( TpPacket->u.F1.info.PacketType == (UCHAR)FUNC2_PACKET_TYPE ))
|
|
{
|
|
if ( Status == NDIS_STATUS_SUCCESS )
|
|
{
|
|
//
|
|
// It is a resend packet, we need to resend it. first check
|
|
// the header and the data in the pacekt.
|
|
//
|
|
|
|
if ( !TpCheckSum( (PUCHAR)&TpPacket->u.F1.info,
|
|
sizeof( PACKET_INFO ) - sizeof( ULONG ),
|
|
(PULONG)&TpPacket->u.F1.info.CheckSum ))
|
|
{
|
|
++OpenP->Receive->Counters->CorruptRecs;
|
|
}
|
|
|
|
// XXX: function for this
|
|
BufMem = (PUCHAR)((PUCHAR)TpPacket + (UCHAR)sizeof( FUNC1_PACKET ));
|
|
|
|
for ( i = 0 ; i < ( BytesTransferred - sizeof( FUNC1_PACKET )) ; i++ )
|
|
{
|
|
if ( BufMem[i] != (UCHAR)( i % 256 ))
|
|
{
|
|
IF_TPDBG( TP_DEBUG_DATA )
|
|
{
|
|
TpPrint1(
|
|
"TpFuncTransferDataComplete: Data Corruption in packet 0x%lX at\n",
|
|
Packet);
|
|
TpPrint3(
|
|
" offset %d into data. Expected 0x%X, found 0x%X.\n\n",
|
|
i,(i % 256),BufMem[i]);
|
|
}
|
|
++OpenP->Receive->Counters->CorruptRecs;
|
|
|
|
IF_TPDBG( TP_DEBUG_BREAKPOINT )
|
|
{
|
|
TpBreakPoint();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Then copy the local adapter address into the source
|
|
// address in the packet header.
|
|
//
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) // Tokenring
|
|
{
|
|
for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ )
|
|
{
|
|
TpPacket->u.F1.media.tr.SrcAddress[i] = OpenP->StationAddress[i];
|
|
}
|
|
}
|
|
else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) // Fddi
|
|
{
|
|
for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ )
|
|
{
|
|
TpPacket->u.F1.media.fddi.SrcAddress[i] = OpenP->StationAddress[i];
|
|
}
|
|
}
|
|
else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_3 ) // Ethernet
|
|
{
|
|
for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ )
|
|
{
|
|
TpPacket->u.F1.media.e.SrcAddress[i] = OpenP->StationAddress[i];
|
|
}
|
|
}
|
|
else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2 ) // Arcnet
|
|
{
|
|
for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ )
|
|
{
|
|
TpPacket->u.F1.media.a.SrcAddress[i] = OpenP->StationAddress[i];
|
|
}
|
|
}
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
//
|
|
// if the NdisTransferData call completed successfully,
|
|
// then we can resend the packet now. Allocate the
|
|
// request handle and set it up as if the request
|
|
// pended. If it does not pend we will reset the
|
|
// flags later before calling the completion routine.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&SendReqHndl,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0(
|
|
"TpFuncTransferDataComplete: unable to allocated request handle\n");
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( SendReqHndl,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
SendReqHndl->Signature = SEND_REQUEST_HANDLE_SIGNATURE;
|
|
SendReqHndl->Open = OpenP;
|
|
SendReqHndl->RequestPended = TRUE;
|
|
SendReqHndl->u.SEND_REQ.Packet = Packet;
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
SendReqHndl->u.SEND_REQ.PacketSize = BytesTransferred + sizeof( MEDIA_HEADER );
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
SendReqHndl->u.SEND_REQ.SendPacket = FALSE;
|
|
|
|
//
|
|
// Now reset the packet to a FUNC1 packet type, and
|
|
// calculate the new checksum.
|
|
//
|
|
|
|
TpPacket->u.F1.info.PacketType = FUNC1_PACKET_TYPE;
|
|
TpPacket->u.F1.info.Signature = FUNC1_PACKET_SIGNATURE;
|
|
|
|
TpPacket->u.F1.info.CheckSum =
|
|
TpSetCheckSum( (PUCHAR)&TpPacket->u.F1.info,
|
|
sizeof( PACKET_INFO ) - sizeof( ULONG ) );
|
|
|
|
//
|
|
// Reference the new request handle off the reserved area.
|
|
//
|
|
|
|
ProtRes->RequestHandle = SendReqHndl;
|
|
//
|
|
// Set the check sum in the PROTOCOL RESERVED Section of the
|
|
// packet header to ensure it is not touched while the packet
|
|
// is in the hands of the MAC.
|
|
//
|
|
|
|
ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) -
|
|
sizeof( ULONG ) );
|
|
|
|
if (OpenP->Receive->ResendReq == NULL)
|
|
{
|
|
OpenP->Receive->ResendReq = SendReqHndl;
|
|
|
|
DueTime.HighPart = -1; // So it will be relative.
|
|
if (OpenP->Receive->ResendType)
|
|
{
|
|
DueTime.LowPart = (ULONG)(-2 * (ONE_HUNDREDTH_SECOND));
|
|
}
|
|
else
|
|
{
|
|
DueTime.LowPart = (ULONG)(-(ONE_HUNDREDTH_SECOND));
|
|
}
|
|
|
|
if ( KeSetTimer(&OpenP->Receive->ResendTimer,
|
|
DueTime,
|
|
&OpenP->Receive->ResendDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncTransferDataComplete set SendTimer while timer existed.\n");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TpFuncResend(OpenP, SendReqHndl);
|
|
}
|
|
}
|
|
else // ( Status == Some Type Failure )
|
|
{
|
|
//
|
|
// The transfer data call failed, increment the counter,
|
|
// and deallocate the resources.
|
|
//
|
|
|
|
IF_TPDBG( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncTransferDataComplete: NdisTransferData failed: returned %s\n",
|
|
TpGetStatus(Status));
|
|
}
|
|
++OpenP->Receive->Counters->XferDataFails;
|
|
|
|
//
|
|
// Now free up the transfer packet resources.
|
|
//
|
|
|
|
NdisUnchainBufferAtFront( Packet,&Buffer );
|
|
NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 );
|
|
TpFreeBuffer( Buffer );
|
|
NdisFreePacket( Packet );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This is just a packet we should receive, count, and drop.
|
|
//
|
|
|
|
BufMem = (PUCHAR)TpPacket;
|
|
|
|
for ( i = 0 ; i < BytesTransferred ; i++ )
|
|
{
|
|
if ( BufMem[i] != (UCHAR)( i % 256 ))
|
|
{
|
|
IF_TPDBG( TP_DEBUG_DATA )
|
|
{
|
|
TpPrint1("TpFuncTransferDataComplete: Data Corruption in packet 0x%lX at\n",
|
|
Packet);
|
|
TpPrint3(
|
|
" offset %d into data. Expected 0x%X found 0x%X.\n",
|
|
i,(i % 256),BufMem[i]);
|
|
}
|
|
++OpenP->Receive->Counters->CorruptRecs;
|
|
|
|
IF_TPDBG( TP_DEBUG_BREAKPOINT )
|
|
{
|
|
TpBreakPoint();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncReceive: NdisTransferData failed: returned %s\n",
|
|
TpGetStatus(Status));
|
|
}
|
|
++OpenP->Receive->Counters->XferDataFails;
|
|
}
|
|
|
|
//
|
|
// Now free up the transfer packet resources.
|
|
//
|
|
|
|
NdisUnchainBufferAtFront( Packet,&Buffer );
|
|
NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 );
|
|
TpFreeBuffer( Buffer );
|
|
NdisFreePacket( Packet );
|
|
}
|
|
|
|
//
|
|
// And finally free up the Request Handle that was allocated
|
|
// in the Receive routine for the call to NdisTransferData.
|
|
//
|
|
|
|
NdisFreeMemory( XferReqHndl,0,0 );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are not expecting a transfer data to complete at this
|
|
// point, so stick this on the Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteTransferData;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would have overflowed it, so
|
|
// mark the Head event overflow flag to show this.
|
|
//
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
//
|
|
// We have a resource, the packet, should we free it? to where?
|
|
// who really owns it?
|
|
//
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
TpFuncResend(POPEN_BLOCK OpenP,
|
|
PTP_REQUEST_HANDLE SendReqHndl)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PNDIS_PACKET Packet = SendReqHndl->u.SEND_REQ.Packet;
|
|
|
|
//
|
|
// Increment the send pending packet counter,
|
|
//
|
|
|
|
++OpenP->Receive->PacketsPending;
|
|
|
|
//
|
|
// and the number of packets sent,
|
|
//
|
|
|
|
++OpenP->Receive->Counters->Sends;
|
|
|
|
//
|
|
// and send it...
|
|
//
|
|
|
|
NdisSend( &Status,
|
|
OpenP->NdisBindingHandle,
|
|
Packet );
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
--OpenP->Receive->PacketsPending;
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG( TP_DEBUG_NDIS_CALLS )
|
|
{
|
|
TpPrint1("TpFuncResendDpc: NdisSend failed: returned %s\n", TpGetStatus(Status));
|
|
}
|
|
//
|
|
// If we are running on TokenRing the following to "failures"
|
|
// are not considered failures NDIS_STATUS_NOT_RECOGNIZED -
|
|
// no one on the ring recognized the address as theirs, or
|
|
// NDIS_STATUS_NOT_COPIED - no one on the ring copied the
|
|
// packet, so we need to special case this and not count
|
|
// these as failures.
|
|
//
|
|
if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) ||
|
|
( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) )
|
|
{
|
|
if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) &&
|
|
( Status != NDIS_STATUS_NOT_COPIED ))
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Send->Counters->SendFails;
|
|
}
|
|
}
|
|
SendReqHndl->RequestPended = FALSE;
|
|
TpFuncSendComplete( OpenP,Packet,Status );
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Receive->Counters->SendPends;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
TpFuncResendDpc(
|
|
IN PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SysArg1,
|
|
IN PVOID SysArg2
|
|
)
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
|
|
PTP_REQUEST_HANDLE SendReqHndl = OpenP->Receive->ResendReq;
|
|
|
|
|
|
UNREFERENCED_PARAMETER( Dpc );
|
|
UNREFERENCED_PARAMETER( SysArg1 );
|
|
UNREFERENCED_PARAMETER( SysArg2 );
|
|
|
|
TpFuncResend(OpenP, SendReqHndl);
|
|
|
|
OpenP->Receive->ResendReq = NULL;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncReceiveDpc(
|
|
IN PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SysArg1,
|
|
IN PVOID SysArg2
|
|
)
|
|
|
|
// --------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// -------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
|
|
LARGE_INTEGER DueTime;
|
|
|
|
UNREFERENCED_PARAMETER( Dpc );
|
|
UNREFERENCED_PARAMETER( SysArg1 );
|
|
UNREFERENCED_PARAMETER( SysArg2 );
|
|
|
|
DueTime.HighPart = -1; // So it will be relative.
|
|
DueTime.LowPart = (ULONG)(-(ONE_SECOND));
|
|
|
|
//
|
|
// If the Irp has been cancelled or the Stop Receive
|
|
// flag has been set then end the test.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if ((( OpenP->Receive->ReceiveIrp == NULL ) ||
|
|
( OpenP->Receive->ReceiveIrp->Cancel == TRUE )) ||
|
|
(( OpenP->Receive->Receiving == TRUE ) &&
|
|
( OpenP->Receive->StopReceiving == TRUE )))
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// The receive test should now stop, so queue the Receive
|
|
// End dpc routine.
|
|
//
|
|
|
|
if ( KeSetTimer(&OpenP->Receive->ReceiveTimer,
|
|
DueTime,
|
|
&OpenP->Receive->ReceiveEndDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncReceiveDpc set StressEnd timer while timer existed.\n");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// Otherwise the test should continue, so insert the next instance
|
|
// of the Receive Dpc in the timer queue and exit. This will queue
|
|
// the next instance of the TpFuncReceiveDpc routine when the
|
|
// timer goes off.
|
|
//
|
|
|
|
if ( KeSetTimer(&OpenP->Receive->ReceiveTimer,
|
|
DueTime,
|
|
&OpenP->Receive->ReceiveDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncReceiveDpc set Receive timer while timer existed.\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncReceiveEndDpc(
|
|
IN PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SysArg1,
|
|
IN PVOID SysArg2
|
|
)
|
|
|
|
// ----------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
//
|
|
// --------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
|
|
LARGE_INTEGER DueTime;
|
|
|
|
UNREFERENCED_PARAMETER( Dpc );
|
|
UNREFERENCED_PARAMETER( SysArg1 );
|
|
UNREFERENCED_PARAMETER( SysArg2 );
|
|
|
|
//
|
|
// See if we have any outstanding packets left to complete. If we do,
|
|
// then we will reset the time to queue this dpc routine again in one
|
|
// second, if after ten requeues the packet(s) has still no completed
|
|
// we assume it will never complete and return the results and finish.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
|
|
if (((( OpenP->Receive->ReceiveIrp != NULL ) &&
|
|
( OpenP->Receive->ReceiveIrp->Cancel == FALSE )) &&
|
|
( OpenP->Receive->PacketsPending != 0 )) &&
|
|
( OpenP->Receive->ReceiveEndDpcCount++ < 10 ))
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
DueTime.HighPart = -1; // So it will be relative.
|
|
DueTime.LowPart = (ULONG)(-(ONE_SECOND));
|
|
|
|
if ( KeSetTimer(&OpenP->Receive->ReceiveTimer,
|
|
DueTime,
|
|
&OpenP->Receive->ReceiveEndDpc ))
|
|
{
|
|
IF_TPDBG ( TP_DEBUG_DPC )
|
|
{
|
|
TpPrint0("TpFuncReceiveEndDpc set ReceiveTimer while timer existed.\n");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If the status has not been reset, then set it to success now.
|
|
//
|
|
|
|
if ( OpenP->Receive->ReceiveIrp->IoStatus.Status == NDIS_STATUS_PENDING )
|
|
{
|
|
OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Now write the RECEIVE results to the output buffer.
|
|
//
|
|
|
|
TpWriteSendReceiveResults( OpenP->Receive->Counters,
|
|
OpenP->Receive->ReceiveIrp );
|
|
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// Now set the receiving flag to indicate that we are no longer
|
|
// RECEIVEing packets.
|
|
//
|
|
|
|
OpenP->Receive->Receiving = FALSE;
|
|
|
|
//
|
|
// and decrement the reference count on the OpenBlock stating this
|
|
// instance of an async test is no longer running, and the adapter
|
|
// may be closed if requested.
|
|
//
|
|
|
|
TpRemoveReference( OpenP );
|
|
|
|
IoMarkIrpPending( OpenP->Receive->ReceiveIrp );
|
|
|
|
IoAcquireCancelSpinLock( &OpenP->Receive->ReceiveIrp->CancelIrql );
|
|
IoSetCancelRoutine( OpenP->Receive->ReceiveIrp,NULL );
|
|
IoReleaseCancelSpinLock( OpenP->Receive->ReceiveIrp->CancelIrql );
|
|
|
|
IoCompleteRequest( OpenP->Receive->ReceiveIrp,IO_NETWORK_INCREMENT );
|
|
|
|
OpenP->Receive->ReceiveIrp = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncGetEvent(
|
|
IN POPEN_BLOCK OpenP
|
|
)
|
|
|
|
// ----
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Status -
|
|
//
|
|
// -----
|
|
|
|
{
|
|
PEVENT_RESULTS OutputBuffer;
|
|
ULONG NextEvent;
|
|
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress );
|
|
|
|
OutputBuffer->Signature = EVENT_RESULTS_SIGNATURE;
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
if ( OpenP->EventQueue->Head == OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is nothing in the Event Queue.
|
|
//
|
|
|
|
OpenP->Irp->IoStatus.Status = TP_STATUS_NO_EVENTS;
|
|
}
|
|
else
|
|
{
|
|
if (( NextEvent = ++OpenP->EventQueue->Tail ) == MAX_EVENT )
|
|
{
|
|
NextEvent = OpenP->EventQueue->Tail = 0;
|
|
}
|
|
|
|
OutputBuffer->TpEventType = OpenP->EventQueue->Events[NextEvent].TpEventType;
|
|
OutputBuffer->QueueOverFlowed = OpenP->EventQueue->Events[NextEvent].Overflow;
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = Unknown;
|
|
OpenP->EventQueue->Events[NextEvent].EventInfo = NULL;
|
|
OpenP->EventQueue->Events[NextEvent].Overflow = FALSE;
|
|
|
|
OpenP->Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
return OpenP->Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncStatus(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS GeneralStatus,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferSize
|
|
)
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
ULONG NextEvent;
|
|
|
|
//
|
|
// We have receive a Status indication, stick it on the
|
|
// Event Queue.
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateStatus;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
|
|
//
|
|
// At this point we could stick the General Status
|
|
// into the EventInfo buffer.
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would overflow it.
|
|
//
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
//
|
|
// Increment the Status Indication counter and set the status
|
|
// completion flag to true to show that a completion is expected.
|
|
//
|
|
|
|
++OpenP->EventQueue->StatusIndicationCount;
|
|
|
|
OpenP->EventQueue->ExpectStatusComplete = TRUE;
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpFuncStatusComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext
|
|
)
|
|
|
|
// ----------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Print out the help message to the debugger screen.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// ---------
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
ULONG NextEvent;
|
|
|
|
NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock );
|
|
|
|
//
|
|
// We have received an unexpected Status Completion, so
|
|
// we are expecting (???) to receive the completion.
|
|
//
|
|
|
|
NextEvent = OpenP->EventQueue->Head + 1;
|
|
|
|
if ( NextEvent == MAX_EVENT )
|
|
{
|
|
NextEvent = 0;
|
|
}
|
|
|
|
if ( NextEvent != OpenP->EventQueue->Tail )
|
|
{
|
|
//
|
|
// There is room to add another event to the event queue.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateStatusComplete;
|
|
OpenP->EventQueue->Head = NextEvent;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event queue is full, and this would overflow it.
|
|
//
|
|
|
|
OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE;
|
|
}
|
|
|
|
//
|
|
// Reset the status indication counter to zero, and set the
|
|
// status completion expected flag to show that no completion
|
|
// routine is expected.
|
|
//
|
|
|
|
OpenP->EventQueue->StatusIndicationCount = 0;
|
|
OpenP->EventQueue->ExpectStatusComplete = FALSE;
|
|
|
|
NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock );
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncSendGo(
|
|
IN POPEN_BLOCK OpenP,
|
|
IN PCMD_ARGS CmdArgs,
|
|
IN UCHAR PacketType
|
|
)
|
|
|
|
// -----
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// ----
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
PTP_REQUEST_HANDLE RequestHandle;
|
|
PGO_PACKET GoPacket;
|
|
PUCHAR p, q;
|
|
USHORT DataSizeShort;
|
|
PNDIS_BUFFER Buffer;
|
|
PNDIS_PACKET Packet;
|
|
PPROTOCOL_RESERVED ProtRes;
|
|
PREQUEST_RESULTS OutputBuffer;
|
|
ULONG i;
|
|
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress );
|
|
|
|
//
|
|
// Allocate the request handle, and init the relevant fields
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&RequestHandle,
|
|
sizeof( TP_REQUEST_HANDLE ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0("TpFuncSendGo: unable to allocated request handle.\n");
|
|
}
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE ));
|
|
}
|
|
|
|
RequestHandle->Signature = GO_REQUEST_HANDLE_SIGNATURE;
|
|
RequestHandle->Open = OpenP;
|
|
|
|
//
|
|
// Now allocate the GoPacket to copy the packet data into.
|
|
//
|
|
|
|
Status = NdisAllocateMemory((PVOID *)&GoPacket,
|
|
sizeof( GO_PACKET ),
|
|
0,
|
|
HighestAddress );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG(TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncSendGo: unable to allocate buffer memory.\n");
|
|
}
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory( (PUCHAR)GoPacket,sizeof( GO_PACKET ));
|
|
}
|
|
|
|
switch ( OpenP->Media->MediumType )
|
|
{
|
|
case NdisMedium802_5:
|
|
GoPacket->go_media.tr.AC = 0x10;
|
|
GoPacket->go_media.tr.FC = 0x40;
|
|
|
|
p = (PUCHAR)&GoPacket->go_media.tr.DestAddress[0];
|
|
q = (PUCHAR)&GoPacket->go_media.tr.SrcAddress[0];
|
|
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
*p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i];
|
|
*q++ = OpenP->StationAddress[i];
|
|
}
|
|
break;
|
|
|
|
case NdisMediumDix:
|
|
case NdisMedium802_3:
|
|
|
|
p = (PUCHAR)&GoPacket->go_media.e.DestAddress[0];
|
|
q = (PUCHAR)&GoPacket->go_media.e.SrcAddress[0];
|
|
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
*p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i];
|
|
*q++ = OpenP->StationAddress[i];
|
|
}
|
|
|
|
DataSizeShort = (USHORT)( sizeof( GO_PACKET ) - OpenP->Media->HeaderSize );
|
|
|
|
GoPacket->go_media.e.PacketSize_Hi = (UCHAR)(DataSizeShort >> 8 );
|
|
GoPacket->go_media.e.PacketSize_Lo = (UCHAR)DataSizeShort;
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
GoPacket->go_media.fddi.FC = 0x57;
|
|
|
|
p = (PUCHAR)&GoPacket->go_media.fddi.DestAddress[0];
|
|
q = (PUCHAR)&GoPacket->go_media.fddi.SrcAddress[0];
|
|
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
*p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i];
|
|
*q++ = OpenP->StationAddress[i];
|
|
}
|
|
break;
|
|
|
|
//
|
|
// STARTCHANGE
|
|
//
|
|
case NdisMediumArcnet878_2:
|
|
GoPacket->go_media.a.ProtocolID = ARCNET_DEFAULT_PROTOCOLID;
|
|
|
|
p = (PUCHAR)&GoPacket->go_media.a.DestAddress[0];
|
|
q = (PUCHAR)&GoPacket->go_media.a.SrcAddress[0];
|
|
|
|
for ( i=0;i<OpenP->Media->AddressLen;i++ )
|
|
{
|
|
*p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i];
|
|
*q++ = OpenP->StationAddress[i];
|
|
}
|
|
break;
|
|
//
|
|
// STOPCHANGE
|
|
//
|
|
|
|
default:
|
|
IF_TPDBG ( TP_DEBUG_RESOURCES )
|
|
{
|
|
TpPrint0("TpFuncSendGo: Unsupported MAC Type\n");
|
|
}
|
|
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
GoPacket->info.Signature = GO_PACKET_SIGNATURE;
|
|
GoPacket->info.TestSignature = CmdArgs->ARGS.PAUSE_GO.TestSignature;
|
|
GoPacket->info.UniqueSignature = OpenP->Pause->UniqueSignature;
|
|
GoPacket->info.PacketType = PacketType;
|
|
|
|
GoPacket->info.CheckSum = TpSetCheckSum((PUCHAR)&GoPacket->info,
|
|
sizeof( GO_PACKET_INFO ) - sizeof( ULONG ) );
|
|
|
|
//
|
|
// Then allocate the buffer that will reference the memory,
|
|
//
|
|
|
|
Buffer = IoAllocateMdl( (PVOID)GoPacket,sizeof( GO_PACKET ),TRUE,FALSE,NULL );
|
|
|
|
if ( Buffer == NULL )
|
|
{
|
|
IF_TPDBG(TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncSendGo: unable to allocate mdl buffer\n");
|
|
}
|
|
NdisFreeMemory( (PVOID)GoPacket,0,0 );
|
|
OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
MmBuildMdlForNonPagedPool( (PMDL)Buffer );
|
|
|
|
//
|
|
// and finally the NDIS_PACKET to pass to the NdisTransferData call.
|
|
//
|
|
|
|
NdisAllocatePacket( &Status,
|
|
&Packet,
|
|
OpenP->Pause->PacketHandle );
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
IF_TPDBG(TP_DEBUG_RESOURCES)
|
|
{
|
|
TpPrint0("TpFuncReceive: unable to allocate resend packet\n");
|
|
}
|
|
IoFreeMdl( Buffer );
|
|
NdisFreeMemory( (PVOID)GoPacket,0,0 );
|
|
OpenP->Irp->IoStatus.Status = Status;
|
|
return Status;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Setup the protocol reserved portion of the packet so the
|
|
// completion routines know what and where to deallocate.
|
|
//
|
|
|
|
ProtRes = PROT_RES( Packet );
|
|
ProtRes->Pool.PacketHandle = OpenP->Pause->PacketHandle;
|
|
ProtRes->InstanceCounters = NULL;
|
|
ProtRes->RequestHandle = RequestHandle;
|
|
RequestHandle->u.SEND_REQ.Packet = Packet;
|
|
}
|
|
|
|
//
|
|
// Now chain the buffer to the packet.
|
|
//
|
|
|
|
NdisChainBufferAtFront( Packet,Buffer );
|
|
|
|
//
|
|
// Set the check sum in the PROTOCOL RESERVED Section of the
|
|
// packet header to ensure it is not touched while the packet
|
|
// is in the hands of the MAC.
|
|
//
|
|
|
|
ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes,
|
|
sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) );
|
|
//
|
|
// And send it.
|
|
//
|
|
|
|
NdisSend( &Status,OpenP->NdisBindingHandle,Packet );
|
|
|
|
if ( Status != NDIS_STATUS_PENDING )
|
|
{
|
|
TpFuncSendComplete( OpenP,Packet,Status );
|
|
}
|
|
else
|
|
{
|
|
// NOTE: should we somehow handle sends failing , or will be catch
|
|
// that on the next iteration??? - this could cause us problems
|
|
// on the go response packet.
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
OutputBuffer->RequestStatus = Status;
|
|
OpenP->Irp->IoStatus.Status = Status;
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpFuncPause(
|
|
IN POPEN_BLOCK OpenP,
|
|
IN PCMD_ARGS CmdArgs,
|
|
IN UCHAR PacketType
|
|
)
|
|
|
|
// ----
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// ----
|
|
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
LARGE_INTEGER TimeOut;
|
|
PREQUEST_RESULTS OutputBuffer;
|
|
|
|
OpenP->Pause->TimeOut = 0;
|
|
|
|
OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress );
|
|
OutputBuffer->RequestStatus = TP_STATUS_TIMEDOUT;
|
|
|
|
TimeOut.HighPart = -1; // so it will be relative.
|
|
TimeOut.LowPart = (ULONG)(-(ONE_SECOND));
|
|
|
|
do
|
|
{
|
|
NdisAcquireSpinLock( &OpenP->Pause->SpinLock );
|
|
|
|
if ( OpenP->Pause->GoReceived == FALSE )
|
|
{
|
|
NdisReleaseSpinLock( &OpenP->Pause->SpinLock );
|
|
|
|
//
|
|
// If the Go packet has not arrived stall for a moment
|
|
// waiting for it to arrive.
|
|
//
|
|
|
|
Status = KeDelayExecutionThread( KernelMode,FALSE,&TimeOut );
|
|
if ( Status != STATUS_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
++OpenP->Pause->TimeOut;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Otherwise we have received a go packet, see if it
|
|
// is the one we are waiting for.
|
|
//
|
|
|
|
if (( CmdArgs->ARGS.PAUSE_GO.TestSignature == OpenP->Pause->TestSignature ) &&
|
|
( OpenP->Pause->PacketType == PacketType ))
|
|
{
|
|
//
|
|
// It is, get out of here.
|
|
//
|
|
OpenP->Pause->GoReceived = FALSE;
|
|
|
|
NdisReleaseSpinLock( &OpenP->Pause->SpinLock );
|
|
|
|
OutputBuffer->RequestStatus = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We received a GO packet with the wrong test signature.
|
|
//
|
|
|
|
OpenP->Pause->GoReceived = FALSE;
|
|
NdisReleaseSpinLock( &OpenP->Pause->SpinLock );
|
|
}
|
|
}
|
|
|
|
} while (( OpenP->Pause->TimeOut < 10 ) && ( OpenP->IrpCancelled == FALSE ));
|
|
|
|
OpenP->Irp->IoStatus.Status = Status;
|
|
return Status;
|
|
}
|
|
|
|
|
|
|