// ------------------------ // // 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 #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;iEnvironment->StressAddress[i] = STRESS_MULTICAST[i]; } break; // // STARTCHANGE // case NdisMediumArcnet878_2: TP_ASSERT (MediaArraySize == NDIS_MEDIUM_ARRAY_SIZE) for ( i=0;iEnvironment->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;iRequestType = 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;iMedia->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;iMedia->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;iMedia->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;iMedia->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;iMedia->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;iMedia->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;iMedia->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; }