You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4921 lines
130 KiB
4921 lines
130 KiB
//
|
|
// Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
|
|
//
|
|
// cm.c
|
|
//
|
|
// IEEE1394 mini-port/call-manager driver
|
|
//
|
|
// Call Manager routines
|
|
//
|
|
// 12/28/1998 JosephJ Created
|
|
// 01/01/1999 ADube modified - Added Remote Node Capability
|
|
//
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Call-manager handlers and completers
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NDIS_STATUS
|
|
NicCmOpenAf(
|
|
IN NDIS_HANDLE CallMgrBindingContext,
|
|
IN PCO_ADDRESS_FAMILY AddressFamily,
|
|
IN NDIS_HANDLE NdisAfHandle,
|
|
OUT PNDIS_HANDLE CallMgrAfContext )
|
|
|
|
// Standard 'CmCmOpenAfHandler' routine called by NDIS when a client
|
|
// requests to open an address family. See DDK doc.
|
|
//
|
|
{
|
|
ADAPTERCB* pAdapter;
|
|
NDIS_HANDLE hExistingAf;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
TIMESTAMP_ENTRY ("==>Open Af");
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmOpenAf" ) );
|
|
|
|
pAdapter = (ADAPTERCB* )CallMgrBindingContext;
|
|
if (pAdapter->ulTag != MTAG_ADAPTERCB)
|
|
{
|
|
ASSERT( !"Atag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
if (AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_1394
|
|
|| AddressFamily->MajorVersion != NDIS_MajorVersion
|
|
|| AddressFamily->MinorVersion != NDIS_MinorVersion)
|
|
{
|
|
return NDIS_STATUS_BAD_VERSION;
|
|
}
|
|
|
|
|
|
do
|
|
{
|
|
AFCB *pAF = NULL;
|
|
|
|
// Allocate and initialize the adress family structure.
|
|
//
|
|
pAF = ALLOC_NONPAGED( sizeof(*pAF), MTAG_AFCB );
|
|
if (!pAF)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
NdisZeroMemory( pAF, sizeof(*pAF) );
|
|
|
|
|
|
// Set a marker for easier memory dump browsing and future assertions.
|
|
//
|
|
pAF->ulTag = MTAG_AFCB;
|
|
|
|
// Save the NDIS handle associated with this AF for use in future
|
|
// NdisXxx calls.
|
|
//
|
|
|
|
ADAPTER_ACQUIRE_LOCK( pAdapter );
|
|
|
|
pAF->NdisAfHandle = NdisAfHandle;
|
|
|
|
|
|
// Initialize the VC list for this AF.
|
|
//
|
|
InitializeListHead( &pAF->AFVCList );
|
|
|
|
|
|
// Set up linkages and references.
|
|
//
|
|
pAF->pAdapter = pAdapter;
|
|
nicReferenceAF( pAF ); // OpenAF
|
|
nicReferenceAdapter( pAdapter ,"NicCmOpenAf "); // OpenAF
|
|
|
|
InsertHeadList(&pAdapter->AFList, &pAF->linkAFCB);
|
|
|
|
|
|
// Return pAF as the address family context.
|
|
//
|
|
|
|
*CallMgrAfContext = (PNDIS_HANDLE )pAF;
|
|
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "NicCmOpenAf Status %x", Status ) );
|
|
|
|
TIMESTAMP_EXIT("<==Open Af ");
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmCloseAf(
|
|
IN NDIS_HANDLE CallMgrAfContext )
|
|
|
|
// Standard 'CmCloseAfHandler' routine called by NDIS when a client
|
|
// requests to close an address family. See DDK doc.
|
|
//
|
|
{
|
|
AFCB* pAF;
|
|
TIMESTAMP_ENTRY ("==>CloseAf");
|
|
|
|
TRACE( TL_T, TM_Cm, ( "NicCmCloseAf" ) );
|
|
|
|
pAF = (AFCB* )CallMgrAfContext;
|
|
|
|
if (pAF->ulTag != MTAG_AFCB)
|
|
{
|
|
ASSERT( !"AFCB?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
|
|
nicSetFlags (&pAF->ulFlags, ACBF_ClosePending);
|
|
|
|
|
|
|
|
// This dereference will eventually lead to us calling
|
|
// NdisMCmCloseAfComplete.
|
|
//
|
|
|
|
//
|
|
// The references that were made in OpenAf
|
|
//
|
|
nicDereferenceAF( pAF );
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "NicCmCloseAf pending" ) );
|
|
|
|
TIMESTAMP_EXIT ("<==Close Af");
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmCreateVc(
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE NdisVcHandle,
|
|
OUT PNDIS_HANDLE ProtocolVcContext )
|
|
|
|
// Standard 'CmCreateVc' routine called by NDIS in response to a
|
|
// client's request to create a virtual circuit. This
|
|
// call must return synchronously.
|
|
//
|
|
{
|
|
NDIS_STATUS status;
|
|
AFCB* pAF;
|
|
VCCB* pVc;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmCreateVc, Af %x",ProtocolAfContext) );
|
|
|
|
pAF = (AFCB* )ProtocolAfContext;
|
|
if (pAF->ulTag != MTAG_AFCB)
|
|
{
|
|
ASSERT( !"Atag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
// Allocate and zero a VC control block, then make any non-zero
|
|
// initializations.
|
|
//
|
|
pVc = ALLOC_VCCB( pAdapter );
|
|
if (!pVc)
|
|
{
|
|
ASSERT( !"Alloc VC?" );
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
NdisZeroMemory( pVc, sizeof(*pVc) );
|
|
|
|
TRACE( TL_I, TM_Cm, ( "NicCmCreateVc $%p", pVc ) );
|
|
|
|
// Set a marker for easier memory dump browsing.
|
|
//
|
|
pVc->Hdr.ulTag = MTAG_VCCB;
|
|
|
|
|
|
// Save the NDIS handle of this VC for use in indications to NDIS later.
|
|
//
|
|
pVc->Hdr.NdisVcHandle = NdisVcHandle;
|
|
|
|
// The VC control block's address is the VC context we return to NDIS.
|
|
//
|
|
*ProtocolVcContext = (NDIS_HANDLE )pVc;
|
|
|
|
// Add a reference to the control block and the associated address family
|
|
// that is removed by LmpCoDeleteVc. Add the linkages.
|
|
//
|
|
pVc->Hdr.pAF = pAF;
|
|
// Initialize the VC's copy of the spinlock to point to the Adapter's spinlock.
|
|
//
|
|
pVc->Hdr.plock = &pAF->pAdapter->lock;
|
|
|
|
nicReferenceVc( pVc ); // Create VC
|
|
nicReferenceAF( pAF ); // Create VC
|
|
|
|
|
|
VC_SET_FLAG (pVc, VCBF_VcCreated);
|
|
|
|
// Add to list of VC's associated with this AF
|
|
//
|
|
AF_ACQUIRE_LOCK (pAF);
|
|
|
|
InsertHeadList(&pAF->AFVCList, &pVc->Hdr.linkAFVcs);
|
|
|
|
AF_RELEASE_LOCK (pAF);
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmCreateVc=0" ) );
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmDeleteVc(
|
|
IN NDIS_HANDLE ProtocolVcContext )
|
|
|
|
// Standard 'CmDeleteVc' routine called by NDIS in response to a
|
|
// client's request to delete a virtual circuit. This
|
|
// call must return synchronously.
|
|
//
|
|
{
|
|
VCCB* pVc = NULL;
|
|
AFCB *pAF = NULL;
|
|
PADAPTERCB pAdapter = NULL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmDelVc($%p)", ProtocolVcContext ) );
|
|
|
|
pVc = (VCCB* )ProtocolVcContext;
|
|
if (pVc->Hdr.ulTag != MTAG_VCCB)
|
|
{
|
|
ASSERT( !"Vtag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
// Set vc flag to deleted, and remove back pointer to AF
|
|
//
|
|
{
|
|
|
|
|
|
// This flag catches attempts by the client to delete the VC twice.
|
|
//
|
|
if (nicReadFlags( &pVc->Hdr.ulFlags ) & VCBF_VcDeleted)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "VC $%p re-deleted?", pVc ) );
|
|
|
|
VC_RELEASE_LOCK ( pVc );
|
|
|
|
ASSERT (0);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
nicSetFlags( &pVc->Hdr.ulFlags, VCBF_VcDeleted );
|
|
|
|
pAF = pVc->Hdr.pAF;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unlink from the AF vc list.
|
|
//
|
|
{
|
|
|
|
nicRemoveEntryList (&pVc->Hdr.linkAFVcs);
|
|
InitializeListHead (&pVc->Hdr.linkAFVcs);
|
|
|
|
pVc->Hdr.pAF = NULL;
|
|
|
|
}
|
|
|
|
|
|
// Remove the references added by NicCmCreateVc.
|
|
//
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
nicDereferenceAF( pAF );
|
|
|
|
//
|
|
// This deref could cause the Vc to be deleted. Don't touch the Vc after that
|
|
//
|
|
nicDereferenceVc( pVc );
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmDelVc 0" ) );
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmMakeCall(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS pCallParameters,
|
|
IN NDIS_HANDLE NdisPartyHandle,
|
|
OUT PNDIS_HANDLE CallMgrPartyContext )
|
|
|
|
// Function Description:
|
|
//
|
|
// Standard 'CmMakeCallHandler' routine called by NDIS when the a client
|
|
// has requested to connect to a remote end-point. See DDK doc.
|
|
//
|
|
// Arguments
|
|
// Call Mge context:
|
|
// Call Parameters
|
|
// Optiuonal NdisPartyHandle
|
|
// Return Value:
|
|
//
|
|
//
|
|
|
|
{
|
|
|
|
PVCCB pVc = (VCCB* )CallMgrVcContext;
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PADAPTERCB pAdapter = NULL;
|
|
NDIS_WORK_ITEM* pMakeCallCompleteWorkItem = NULL;
|
|
|
|
|
|
PCO_MEDIA_PARAMETERS pMediaParams = pCallParameters->MediaParameters;
|
|
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCall" ) );
|
|
|
|
nicInterceptMakeCallParameters(pMediaParams);
|
|
|
|
|
|
do
|
|
{
|
|
|
|
|
|
if (NdisPartyHandle != NULL ||
|
|
pVc == NULL ||
|
|
pCallParameters == NULL ||
|
|
pCallParameters->MediaParameters == NULL ||
|
|
pCallParameters->MediaParameters->MediaSpecific.ParamType != NIC1394_MEDIA_SPECIFIC ||
|
|
pN1394Params->MTU == 0)
|
|
{
|
|
//
|
|
// We do not support these parameters
|
|
//
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
ASSERT (pAdapter != NULL);
|
|
|
|
|
|
//
|
|
// Reference the Vc so it does not go during this makeCall
|
|
// This is decremented in the failure code path or the workitem or
|
|
// when the call is closed
|
|
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
nicReferenceVc (pVc);
|
|
|
|
//
|
|
// Erase all references to past calls
|
|
//
|
|
VC_CLEAR_FLAGS (pVc, VCBM_NoActiveCall);
|
|
|
|
VC_SET_FLAG (pVc, VCBF_MakeCallPending);
|
|
//
|
|
// Initialize the Call's refcount to 1 beacuse we are about to begin to allocate resources to the MakeCall
|
|
// This will be decremented in the closecall handler. Or in the failure code path
|
|
//
|
|
nicInitializeCallRef (pVc);
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
|
|
pVc->Hdr.pCallParameters = pCallParameters;
|
|
|
|
NdisStatus = nicCmGenericMakeCallInit (pVc);
|
|
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "nicCmGenericMakeCallInit did not succeed- Make Call FAILED($%p)", CallMgrVcContext ) );
|
|
break;
|
|
}
|
|
//
|
|
// If status is pending it means that we want to make this an asynchronous call
|
|
// The completing th
|
|
|
|
pMakeCallCompleteWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
|
|
|
|
if (pMakeCallCompleteWorkItem == NULL)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem - Make Call FAILED($%p)", CallMgrVcContext ) );
|
|
NdisStatus = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Now schedule the work item so it runs at passive level and pass the Vc as
|
|
// an argument
|
|
//
|
|
|
|
NdisInitializeWorkItem ( pMakeCallCompleteWorkItem,
|
|
(NDIS_PROC)nicCmMakeCallComplete,
|
|
(PVOID)pVc );
|
|
|
|
NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
|
|
|
|
NdisScheduleWorkItem (pMakeCallCompleteWorkItem);
|
|
|
|
NdisStatus = NDIS_STATUS_PENDING;
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS (NdisStatus))
|
|
{
|
|
|
|
//
|
|
// Clean up, close the ref on the Calls, Deref the Call. And Update the Vc
|
|
// to show that we have failed the make call
|
|
//
|
|
|
|
nicCmGenrericMakeCallFailure (pVc);
|
|
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCall, Vc %x, Status%x", pVc, NdisStatus ) );
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmGenericMakeCallInitChannels (
|
|
IN PCHANNEL_VCCB pChannelVc,
|
|
VC_SEND_RECEIVE VcType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Initialze handlers for Send / Recv Channels
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; // As there are no allocations
|
|
PCO_MEDIA_PARAMETERS pMediaParams = pChannelVc->Hdr.pCallParameters->MediaParameters;
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
|
|
|
|
|
|
if ((pN1394Params->Flags & NIC1394_VCFLAG_ALLOCATE) == NIC1394_VCFLAG_ALLOCATE)
|
|
{
|
|
TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Vc %x nneds to allocate channel %x",
|
|
pChannelVc,
|
|
pN1394Params->Destination.Channel) );
|
|
|
|
|
|
VC_SET_FLAG (pChannelVc, VCBF_NeedsToAllocateChannel);
|
|
}
|
|
|
|
switch (VcType)
|
|
{
|
|
case TransmitAndReceiveVc:
|
|
{
|
|
//
|
|
// Channels will be defaulted to have Send And Receive Capabilities
|
|
//
|
|
TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Transmit and Receive Vc Vc %x", pChannelVc ) );
|
|
|
|
pChannelVc->Hdr.VcType = NIC1394_SendRecvChannel;
|
|
|
|
pChannelVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitSendRecvChannelVc;
|
|
pChannelVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendRecvChannel;
|
|
pChannelVc->Hdr.VcHandlers.SendPackets = AsyncStreamSendPacketsHandler;
|
|
break;
|
|
}
|
|
|
|
case ReceiveVc:
|
|
{
|
|
TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Receive Vc %x", pChannelVc ) );
|
|
pChannelVc->Hdr.VcType = NIC1394_RecvChannel;
|
|
|
|
pChannelVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitSendRecvChannelVc;
|
|
pChannelVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendRecvChannel;
|
|
pChannelVc->Hdr.VcHandlers.SendPackets = DummySendPacketsHandler;
|
|
|
|
break;
|
|
}
|
|
|
|
case TransmitVc:
|
|
{
|
|
TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Transmit Vc Vc %x", pChannelVc ) );
|
|
pChannelVc->Hdr.VcType = NIC1394_SendChannel;
|
|
|
|
pChannelVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallSendChannel ;
|
|
pChannelVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendChannel;
|
|
pChannelVc->Hdr.VcHandlers.SendPackets = AsyncStreamSendPacketsHandler;
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmGenericMakeCallInitFifo (
|
|
IN PVCCB pVc,
|
|
VC_SEND_RECEIVE VcType
|
|
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Initializes Fifo Vcs'. This only fails a recv fifo is asked for and the
|
|
adapter already has one.
|
|
|
|
Arguments:
|
|
pVc
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; //As there are no allocations
|
|
PCO_MEDIA_PARAMETERS pMediaParams = pVc->Hdr.pCallParameters->MediaParameters;
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
|
|
|
|
switch (VcType)
|
|
{
|
|
|
|
case ReceiveVc:
|
|
{
|
|
//
|
|
// Recv FifoVcs
|
|
//
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB) pVc;
|
|
|
|
ASSERT(pMediaParams->Flags & RECEIVE_VC);
|
|
|
|
TRACE( TL_V, TM_Cm, ( " MakeCall - AsyncReceiveVc Vc %x", pVc ) );
|
|
|
|
pVc->Hdr.VcType = NIC1394_RecvFIFO;
|
|
|
|
pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitRecvFIFOVc;
|
|
pVc->Hdr.VcHandlers.SendPackets = DummySendPacketsHandler;
|
|
pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallRecvFIFO;
|
|
|
|
|
|
//
|
|
// There are two reasons to fail a RecvFIFO Make call.
|
|
// One, a REcvFIFO already exists and second UniqueId != 0
|
|
//
|
|
|
|
if (pAdapter->pRecvFIFOVc == NULL && pN1394Params->Destination.FifoAddress.UniqueID == 0 )
|
|
{
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
pAdapter->pRecvFIFOVc = (PRECVFIFO_VCCB)pVc;
|
|
//
|
|
// Since the adapter now has a pointer to the Vc, increment the Refcount.
|
|
// This will be decremented in the CloseCall
|
|
//
|
|
nicReferenceVc (pVc);
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
}
|
|
else
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Adapter at %x, already has a recvFIFO. Field is at %x", pAdapter, &pAdapter->pRecvFIFOVc ) );
|
|
ASSERT (pAdapter->pRecvFIFOVc == NULL);
|
|
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
|
|
pVc->Hdr.VcHandlers.MakeCallHandler = NULL;
|
|
pVc->Hdr.VcHandlers.CloseCallHandler = NULL;
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case TransmitVc:
|
|
{
|
|
//
|
|
// Send Fifo Vcs
|
|
//
|
|
|
|
TRACE( TL_V, TM_Cm, ( " MakeCall - AsyncTransmitVc Vc %x", pVc ) );
|
|
|
|
pVc->Hdr.VcType = NIC1394_SendFIFO;
|
|
|
|
pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitSendFIFOVc;
|
|
pVc->Hdr.VcHandlers.SendPackets = AsyncWriteSendPacketsHandler;
|
|
pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendFIFO;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TransmitAndReceiveVc:
|
|
default:
|
|
{
|
|
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
}
|
|
|
|
return NdisStatus;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmGenericMakeCallMutilChannel (
|
|
IN PVCCB pVc,
|
|
VC_SEND_RECEIVE VcType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Init the handlers
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
TRACE( TL_A, TM_Cm, ( "Make Call Recvd for MultiChannel %x ", pVc) );
|
|
|
|
pVc->Hdr.VcType = NIC1394_MultiChannel;
|
|
|
|
pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallMultiChannel ;
|
|
pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallMultiChannel ;
|
|
pVc->Hdr.VcHandlers.SendPackets = AsyncStreamSendPacketsHandler;
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
nicCmGenericMakeCallEthernet(
|
|
IN PVCCB pVc,
|
|
IN VC_SEND_RECEIVE VcType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Init the handlers
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
TRACE( TL_A, TM_Cm, ( "Make Call Recvd for Ethernet %x ", pVc) );
|
|
|
|
pVc->Hdr.VcType = NIC1394_Ethernet;
|
|
|
|
pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitEthernet;
|
|
pVc->Hdr.VcHandlers.SendPackets = nicEthernetVcSend;
|
|
pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallEthernet ;
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmGenericMakeCallInit (
|
|
IN PVCCB pVc
|
|
)
|
|
|
|
// Function Description:
|
|
//
|
|
// This initializes the VcType and Copied the Media Parameters over
|
|
// Initialized VCType to SendChannel, RecvChannel, SendAndRecvChanne,
|
|
// SendFifo,
|
|
//
|
|
// Arguments
|
|
// Vc - Vc that needs to be initalized
|
|
//
|
|
// Return Value:
|
|
// Success - as no memory allocation takes place
|
|
|
|
|
|
// This function should not do anything that can fail.
|
|
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
|
|
VC_SEND_RECEIVE VcType = InvalidType;
|
|
|
|
PCO_MEDIA_PARAMETERS pMediaParams = pVc->Hdr.pCallParameters->MediaParameters;
|
|
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmGenericMakeCallInit pVc %x", pVc ) );
|
|
|
|
pVc->Hdr.Nic1394MediaParams = *pN1394Params;
|
|
ASSERT(pVc->Hdr.pAF!=NULL);
|
|
pVc->Hdr.pGeneration = &pVc->Hdr.pAF->pAdapter->Generation;
|
|
|
|
//
|
|
// Figure out if this is send or receive Vc Or both
|
|
//
|
|
do
|
|
{
|
|
if ((pMediaParams->Flags & (TRANSMIT_VC |RECEIVE_VC)) == TRANSMIT_VC)
|
|
{
|
|
VcType = TransmitVc;
|
|
break;
|
|
}
|
|
|
|
if ((pMediaParams->Flags & (TRANSMIT_VC |RECEIVE_VC)) == RECEIVE_VC)
|
|
{
|
|
VcType = ReceiveVc;
|
|
break;
|
|
}
|
|
if ((pMediaParams->Flags & (TRANSMIT_VC |RECEIVE_VC)) == (TRANSMIT_VC |RECEIVE_VC) )
|
|
{
|
|
VcType = TransmitAndReceiveVc;
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
ASSERT (VcType <= TransmitAndReceiveVc);
|
|
|
|
|
|
switch (pN1394Params->Destination.AddressType)
|
|
{
|
|
case NIC1394AddressType_Channel:
|
|
{
|
|
NdisStatus = nicCmGenericMakeCallInitChannels ((PCHANNEL_VCCB)pVc, VcType);
|
|
|
|
break;
|
|
}
|
|
case NIC1394AddressType_FIFO:
|
|
{
|
|
//
|
|
// Now we are in FIFO land.
|
|
//
|
|
|
|
NdisStatus = nicCmGenericMakeCallInitFifo (pVc, VcType );
|
|
|
|
break;
|
|
}
|
|
|
|
case NIC1394AddressType_MultiChannel:
|
|
{
|
|
|
|
NdisStatus = nicCmGenericMakeCallMutilChannel (pVc, VcType );
|
|
|
|
break;
|
|
}
|
|
|
|
case NIC1394AddressType_Ethernet:
|
|
{
|
|
NdisStatus = nicCmGenericMakeCallEthernet(pVc, VcType );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ASSERT (pN1394Params->Destination.AddressType<=NIC1394AddressType_Ethernet);
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmGenericMakeCallInit pVc %x, Status %x",pVc , NdisStatus) );
|
|
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
nicCmGenrericMakeCallFailure (
|
|
IN PVCCB pVc
|
|
)
|
|
// Function Description:
|
|
// Does the clean up on the VcHDr structure. Will cleanup the Destination, VcType
|
|
// and Vc. Initialize Handler. Special case - Recv VC
|
|
// Arguments
|
|
// PVCCB : Vc on which cleanup need to be done.
|
|
// Return Value:
|
|
// None
|
|
{
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicGenrericMakeCallFailure pVc %x, ",pVc ) );
|
|
|
|
|
|
|
|
//
|
|
// First, we need to make sure if adapter's VC is the same as this VC,
|
|
// otherwise the adapters'recv VC is Valid Vc currently in Use. Do not touch it.
|
|
//
|
|
|
|
if (pVc->Hdr.VcType == NIC1394_RecvFIFO &&
|
|
pVc->Hdr.pAF->pAdapter->pRecvFIFOVc == (PRECVFIFO_VCCB)pVc)
|
|
{
|
|
|
|
//
|
|
// This is the reference that was added GenericInitVc function
|
|
// and only applied to Recv VC's
|
|
//
|
|
nicDereferenceVc (pVc);
|
|
}
|
|
|
|
VC_ACQUIRE_LOCK(pVc)
|
|
|
|
pVc->Hdr.VcHandlers.MakeCallHandler = NULL;
|
|
pVc->Hdr.VcHandlers.CloseCallHandler = NULL;
|
|
|
|
pVc->Hdr.VcType = NIC1394_Invalid_Type;
|
|
|
|
|
|
NdisZeroMemory (&pVc->Hdr.Nic1394MediaParams ,
|
|
sizeof (pVc->Hdr.Nic1394MediaParams) );
|
|
|
|
nicCloseCallRef (pVc);
|
|
|
|
//
|
|
// Mark the Vc Flags, with a MakeCall Failed
|
|
//
|
|
VC_CLEAR_FLAGS(pVc ,VCBF_MakeCallPending);
|
|
|
|
VC_SET_FLAG (pVc, VCBF_MakeCallFailed);
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicGenrericMakeCallFailure pVc %x, ",pVc ) );
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
nicCmMakeCallComplete (
|
|
NDIS_WORK_ITEM* pMakeCallCompleteWorkItem,
|
|
IN PVOID Context
|
|
)
|
|
// Function:
|
|
// This function is used to complete a Make Call. This can be done synchronously
|
|
// or asynchronous. If a status pending was passed to this function, it will complete using
|
|
// the asynchronous route
|
|
//
|
|
// If everytrhing succeeds, one Ref to the Vc will be passed through and that will be decremented
|
|
// when the call is closed
|
|
// This function should never return NDIS_STATUS_PENDING. Will be called as a WorkItem
|
|
{
|
|
|
|
PVCCB pVc = (PVCCB)Context;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallComplete ,pVc %x",pVc ) );
|
|
|
|
//
|
|
// Reference the Vc as we want the Vc structure to stay alive till
|
|
// the end of the make call complete
|
|
//
|
|
nicReferenceVc (pVc);
|
|
|
|
|
|
//
|
|
// Call the Initialize handler for the VC so that it can be initialized
|
|
//
|
|
|
|
ASSERT (pVc->Hdr.VcHandlers.MakeCallHandler != NULL);
|
|
|
|
NdisStatus = (*pVc->Hdr.VcHandlers.MakeCallHandler) (pVc);
|
|
|
|
MATCH_IRQL;
|
|
|
|
if (NdisStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
VC_ACQUIRE_LOCK(pVc);
|
|
//
|
|
// Now mark the Vc as active
|
|
//
|
|
|
|
|
|
VC_SET_FLAG( pVc, VCBF_VcActivated);
|
|
|
|
VC_CLEAR_FLAGS(pVc ,VCBF_MakeCallPending);
|
|
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// call the clean up routine to bring the Vc back to its old state
|
|
//
|
|
|
|
nicCmMakeCallCompleteFailureCleanUp (pVc);
|
|
|
|
//
|
|
// Dereference the call that we are about to fail. This reference was made in
|
|
// the beginning of make call routine. when the callref ==0, the Vc will be
|
|
// dereferenced as well
|
|
//
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
VC_SET_FLAG (pVc, VCBF_MakeCallFailed);
|
|
|
|
VC_CLEAR_FLAGS(pVc ,VCBF_MakeCallPending);
|
|
|
|
nicDereferenceCall (pVc, "nicCmMakeCallComplete");
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
}
|
|
|
|
|
|
MATCH_IRQL;
|
|
|
|
//
|
|
// Complete the call with the correct status
|
|
//
|
|
TRACE( TL_N, TM_Cm, ( "Completing the Make Call , Vc %x, Status %x", pVc, NdisStatus ) );
|
|
|
|
|
|
|
|
|
|
NdisCmMakeCallComplete(NdisStatus,
|
|
pVc->Hdr.NdisVcHandle,
|
|
NULL,
|
|
NULL,
|
|
pVc->Hdr.pCallParameters );
|
|
|
|
|
|
|
|
TRACE( TL_I, TM_Cm, ( "Called NdisCmMakeCallComplete, Vc %x, Status%x", pVc, NdisStatus ) );
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallComplete, Vc %x, Status%x", pVc, NdisStatus ) );
|
|
|
|
|
|
FREE_NONPAGED (pMakeCallCompleteWorkItem);
|
|
|
|
NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
|
|
//
|
|
// This will cause the Vc Refcount to go to zero if the Make Call fails
|
|
//
|
|
nicDereferenceVc (pVc);
|
|
|
|
MATCH_IRQL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmMakeCallInitRecvFIFOVc(
|
|
IN OUT PVCCB pVc
|
|
)
|
|
// Function Description:
|
|
//
|
|
// This function allocates, packet pool, populates the Slist
|
|
// allocates the address range and
|
|
// inserts the Vc into the Adapter->pRecvFifoVc field
|
|
//
|
|
// Will succeed the call, if this process was successful on 1 remote node
|
|
// Arguments
|
|
// PVCCB : pVc that the call is made on
|
|
//
|
|
//
|
|
// Return Value:
|
|
// Success: If all allocations succeeded for just 1 remote node
|
|
|
|
|
|
{
|
|
|
|
PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB) pVc;
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
|
|
REMOTE_NODE *pRemoteNode = NULL;
|
|
PADAPTERCB pAdapter = pRecvFIFOVc->Hdr.pAF->pAdapter;
|
|
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = &pVc->Hdr.Nic1394MediaParams;
|
|
UINT64 UniqueId = pN1394Params->Destination.FifoAddress.UniqueID;
|
|
PLIST_ENTRY pPdoListEntry = NULL;
|
|
BOOLEAN fWaitSuccessful = FALSE;
|
|
BOOLEAN fInitRecvFifoDataStructures = FALSE;
|
|
BOOLEAN fNeedToWait = FALSE;
|
|
PNIC1394_FIFO_ADDRESS pFifoAddress = NULL;
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallInitRecvFIFOVc pRecvFIFOVc %x ", pRecvFIFOVc) );
|
|
|
|
ASSERT (pAdapter != NULL);
|
|
ASSERT (KeGetCurrentIrql()==PASSIVE_LEVEL);
|
|
|
|
pFifoAddress = &pN1394Params->Destination.FifoAddress;
|
|
|
|
UniqueId = pFifoAddress->UniqueID;
|
|
do
|
|
{
|
|
|
|
|
|
|
|
NdisStatus = nicInitRecvFifoDataStructures (pRecvFIFOVc);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( " nicInitRecvFifoDataStructures FAILED pRecvFIFOVc is %x, UniqueId %I64x ", pRecvFIFOVc) );
|
|
break;
|
|
}
|
|
|
|
fInitRecvFifoDataStructures = TRUE;
|
|
|
|
//
|
|
// This field is not used by a RecvFIFO because it has multiple Pdos
|
|
//
|
|
pRecvFIFOVc->Hdr.pRemoteNode = NULL;
|
|
|
|
NdisStatus = nicAllocateAddressRange(pAdapter, pRecvFIFOVc);
|
|
|
|
if(NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Unable to get Pdo and allocate addresses, call FAILED ,pRecvFIFOVc is %x", pRecvFIFOVc) );
|
|
|
|
ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
ASSERT(pRecvFIFOVc->PacketPool.Handle != NULL);
|
|
ASSERT(pRecvFIFOVc->Hdr.MTU != 0);
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Undo all allocated memory
|
|
//
|
|
TRACE( TL_A, TM_Cm, ( "Failing the Make Call for Vc %x" , pVc) );
|
|
|
|
if (fInitRecvFifoDataStructures == TRUE)
|
|
{
|
|
nicUnInitRecvFifoDataStructures (pRecvFIFOVc);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
TRACE( TL_I, TM_Cm, ( "pVc's Offset High %4x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_High ) );
|
|
TRACE( TL_I, TM_Cm, ( "pVc's Offset Low %x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_Low ) );
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallInitRecvFIFOVc %x",NdisStatus ) );
|
|
|
|
MATCH_IRQL;
|
|
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmMakeCallInitSendFIFOVc(
|
|
IN OUT PVCCB pVc
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This initializes a Send Fifo Make Call.
|
|
It
|
|
i) finds the remote node using the make call parameters
|
|
ii) inititalizes strcutures
|
|
|
|
Arguments:
|
|
pVc - Vc that the make call is done on.
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
//
|
|
|
|
|
|
{
|
|
|
|
PSENDFIFO_VCCB pSendFIFOVc = (PSENDFIFO_VCCB) pVc;
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
|
|
UINT Generation = 0;
|
|
PREMOTE_NODE pRemoteNode = NULL;
|
|
PADAPTERCB pAdapter = pSendFIFOVc->Hdr.pAF->pAdapter;
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = NULL;
|
|
UINT64 UniqueId = 0;
|
|
PNIC1394_FIFO_ADDRESS pFifoAddress = NULL;
|
|
ULONG Speed;
|
|
ULONG MaxBufferSize;
|
|
ULONG RemoteMaxRec;
|
|
BOOLEAN fDeRefRemoteNode = FALSE;
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallInitSendFIFOVc pSendFIFOVc %x", pSendFIFOVc ) );
|
|
|
|
|
|
pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pVc->Hdr.pCallParameters->MediaParameters->MediaSpecific.Parameters[0];
|
|
|
|
ASSERT (pN1394Params->Destination.AddressType == NIC1394AddressType_FIFO);
|
|
|
|
|
|
pFifoAddress = &pN1394Params->Destination.FifoAddress;
|
|
|
|
UniqueId = pFifoAddress->UniqueID;
|
|
|
|
|
|
TRACE( TL_V, TM_Cm, ( "FifoAddress %x, UniqueId %I64x, Hi %.4x, Lo %x",
|
|
pFifoAddress, pFifoAddress->UniqueID,
|
|
pFifoAddress->Off_High, pFifoAddress->Off_Low ) );
|
|
|
|
do
|
|
{
|
|
|
|
//
|
|
// Get the Pdo that corresponds with the UniqueId
|
|
//
|
|
ASSERT(pSendFIFOVc->Hdr.pAF->pAdapter != NULL);
|
|
|
|
|
|
|
|
NdisStatus = nicFindRemoteNodeFromAdapter( pSendFIFOVc->Hdr.pAF->pAdapter,
|
|
NULL,
|
|
UniqueId,
|
|
&pRemoteNode);
|
|
|
|
if(NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Unable to Find Pdo, call FAILED ,pSendFIFOVc is %x, UniqueId %I64x ", pSendFIFOVc, UniqueId ) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ASSERT (pRemoteNode != NULL);
|
|
|
|
//
|
|
// nicFindRemoteNodeFromAdapter ref's pRemoteNode on success.
|
|
// We need to deref it if we're not going to be using it.
|
|
// Let's start by assuming we aren't.
|
|
//
|
|
fDeRefRemoteNode = TRUE;
|
|
|
|
//
|
|
// Get the Generation Count of the device
|
|
//
|
|
NdisStatus = nicGetGenerationCount ( pRemoteNode->pAdapter, &Generation);
|
|
|
|
if(NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "GET GENERATION FAILED ,pSendFIFOVc is %x", pSendFIFOVc ) );
|
|
|
|
ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
TRACE( TL_V, TM_Cm, ( "Found PdoCb %x for pSendFIFOVc %x", pRemoteNode,pSendFIFOVc ) );
|
|
|
|
//
|
|
// We check if the remote node's pdo is active. if so, then insert the Vc into the
|
|
// PdoCb's list. Now responsibility for any removals has moved to the remove remote node code path
|
|
//
|
|
|
|
//
|
|
// Get the max buffer size that can be transmitted on this link
|
|
//
|
|
NdisStatus = nicQueryRemoteNodeCaps (pAdapter,
|
|
pRemoteNode,
|
|
// FALSE, // FALSE== not from cache.
|
|
&Speed,
|
|
&MaxBufferSize,
|
|
&RemoteMaxRec);
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
if (REMOTE_NODE_ACTIVE (pRemoteNode) == FALSE)
|
|
{
|
|
NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Reference the call in the Vc as the RemoteNodePdo is about to have a pointer to it., This is dereferenced
|
|
// in the CloseCallComplete Send Fifo Function. we have the lock
|
|
//
|
|
nicReferenceCall (pVc, "nicCmMakeCallInitSendFIFOVc");
|
|
|
|
//
|
|
// We keep the reference to pRemoteNode that was added by FindRemoteNode.
|
|
// Derefed in SendFifoCloseCall when the pointer is nulled
|
|
//
|
|
fDeRefRemoteNode = FALSE;
|
|
|
|
//
|
|
// Insert the Vc into the Pdo's List
|
|
//
|
|
|
|
InsertTailList (&pRemoteNode->VcList, &pSendFIFOVc->Hdr.SinglePdoVcLink);
|
|
|
|
TRACE( TL_V, TM_Cm, ( "Inserted Vc %x into Pdo List %x ", pSendFIFOVc, pRemoteNode) );
|
|
|
|
|
|
|
|
//
|
|
// This is not protected by the lock, but we are gauranteed that the Call will not be closed
|
|
// and the Pdo will not be be removed from the system at this point, So we can update
|
|
// this field.
|
|
//
|
|
pSendFIFOVc->Hdr.pRemoteNode = pRemoteNode;
|
|
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
|
|
//
|
|
// Acquire the spin lock and initialize the structures
|
|
//
|
|
VC_ACQUIRE_LOCK (pSendFIFOVc);
|
|
|
|
pSendFIFOVc->Hdr.MTU = pN1394Params->MTU;
|
|
|
|
|
|
pSendFIFOVc->Hdr.pGeneration = &pAdapter->Generation;
|
|
|
|
pSendFIFOVc->FifoAddress = pN1394Params->Destination.FifoAddress;
|
|
|
|
pSendFIFOVc->MaxSendSpeed = pN1394Params->MaxSendSpeed;
|
|
|
|
pSendFIFOVc->Hdr.MaxPayload = min (pN1394Params->MTU, (ULONG)pN1394Params->MaxSendBlockSize);
|
|
|
|
|
|
VC_RELEASE_LOCK (pSendFIFOVc);
|
|
|
|
|
|
|
|
//
|
|
// Validate the parameters for the Vc
|
|
//
|
|
ASSERT(pSendFIFOVc->Hdr.pRemoteNode != NULL);
|
|
ASSERT(pSendFIFOVc->Hdr.pRemoteNode->pPdo != NULL);
|
|
ASSERT(pSendFIFOVc->Hdr.pGeneration != NULL);
|
|
ASSERT(pSendFIFOVc->MaxSendSpeed != 0);
|
|
ASSERT(pSendFIFOVc->Hdr.MTU != 0);
|
|
|
|
|
|
TRACE( TL_V, TM_Cm, ( " Generation is %x", *pSendFIFOVc->Hdr.pGeneration ) );
|
|
|
|
TRACE( TL_N, TM_Cm, ( " Pdo in the Send VC is %x", pSendFIFOVc->Hdr.pRemoteNode->pPdo) );
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
pSendFIFOVc->MaxSendSpeed = min(pSendFIFOVc->MaxSendSpeed,Speed);
|
|
pSendFIFOVc->Hdr.MaxPayload = min (pSendFIFOVc->Hdr.MaxPayload, MaxBufferSize);
|
|
|
|
#ifdef LOWER_SEND_SPEED
|
|
|
|
pSendFIFOVc->MaxSendSpeed = SCODE_200_RATE;//min(pSendFIFOVc->MaxSendSpeed,Speed);
|
|
|
|
pSendFIFOVc->Hdr.MaxPayload = ASYNC_PAYLOAD_200_RATE ;// min(pSendFIFOVc->Hdr.MaxPayload, MaxBufferSize);
|
|
#endif
|
|
|
|
TRACE( TL_V, TM_Cm, ( " MaxSendSpeed is %x", pSendFIFOVc->MaxSendSpeed) );
|
|
TRACE( TL_V, TM_Cm, ( " MaxPayload is %d", pSendFIFOVc->Hdr.MaxPayload ) );
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
if ( NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// The Make is going to be failed asynchrnously
|
|
// If we allocated in resources, we must free them
|
|
// In this case, there have been no Resources allocated
|
|
//
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE( TL_I, TM_Cm, ( " pVc's Offset High %4x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_High ) );
|
|
TRACE( TL_I, TM_Cm, ( " pVc's Offset Low %x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_Low ) );
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallInitSendFIFOVc %x",NdisStatus ) );
|
|
|
|
if (fDeRefRemoteNode)
|
|
{
|
|
nicDereferenceRemoteNode (pRemoteNode, FindRemoteNodeFromAdapterFail);
|
|
}
|
|
|
|
|
|
MATCH_IRQL;
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmMakeCallInitSendRecvChannelVc(
|
|
IN OUT PVCCB pVc
|
|
)
|
|
// Function Description:
|
|
//
|
|
// Arguments
|
|
// pVc, This is the send fifo that needs to be initilaized
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Success if the irps sent to the driver succeed
|
|
//
|
|
//
|
|
|
|
|
|
{
|
|
|
|
PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = NULL;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
ULONG Channel = 64;
|
|
HANDLE hResource=NULL;
|
|
ULONG MaxBufferSize = 0;
|
|
ULONG QuadletsToStrip = 0;
|
|
PISOCH_DESCRIPTOR pIsochDescriptor = NULL;
|
|
CYCLE_TIME CycleTime;
|
|
PDEVICE_OBJECT ArrayRemotePDO[64];
|
|
//NDIS_HANDLE hPacketPoolHandle=NULL;
|
|
BOOLEAN fAnyChannel = FALSE;
|
|
NIC_PACKET_POOL PacketPool;
|
|
STORE_CURRENT_IRQL;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallInitSendRecvChannelVc pVc %x", pVc ) );
|
|
|
|
|
|
ASSERT (pAdapter != NULL);
|
|
|
|
pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pVc->Hdr.pCallParameters->MediaParameters->MediaSpecific.Parameters[0];
|
|
|
|
Channel = pN1394Params->Destination.Channel;
|
|
|
|
TRACE( TL_V, TM_Cm, ( "Channel %x", Channel ) );
|
|
|
|
do
|
|
{
|
|
PacketPool.Handle = NULL;
|
|
|
|
ADAPTER_ACQUIRE_LOCK( pAdapter );
|
|
|
|
|
|
//
|
|
// Set up the the VDO, so that all channel operations can use it
|
|
//
|
|
pVc->Hdr.pLocalHostVDO = pAdapter->pNextDeviceObject;
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK( pAdapter );
|
|
|
|
|
|
NdisAllocatePacketPoolEx ( &NdisStatus,
|
|
&PacketPool.Handle,
|
|
MIN_PACKET_POOL_SIZE,
|
|
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
|
|
sizeof (RSVD) );
|
|
|
|
if (PacketPool.Handle == NULL || NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK (TM_Cm, ( "NdisAllocatePacketPoolEx FAILED" ) );
|
|
}
|
|
|
|
//
|
|
// Reference Call for Packet Pool Handle
|
|
//
|
|
nicReferenceCall ((PVCCB)pChannelVc, "nicCmMakeCallInitSendRecvChannelVc - packet pool ");
|
|
|
|
|
|
PacketPool.AllocatedPackets = 0;
|
|
|
|
pChannelVc->Hdr.MTU = pN1394Params->MTU;
|
|
pChannelVc->PacketPool= PacketPool;
|
|
NdisInitializeEvent(&pChannelVc->LastDescReturned);
|
|
|
|
|
|
//
|
|
// This function should do its own cleanup
|
|
//
|
|
NdisStatus = nicAllocateChannelResourcesAndListen (pAdapter,
|
|
pChannelVc );
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK (TM_Cm, ( "nicAllocateChannelResourcesAndListen FAILED" ) );
|
|
}
|
|
//
|
|
// Return the allocated channel number, if this is an any channel
|
|
// or broadcast channel call
|
|
//
|
|
if ((pN1394Params->Destination.Channel == NIC1394_ANY_CHANNEL) &&
|
|
(pN1394Params->Destination.AddressType == NIC1394AddressType_Channel))
|
|
{
|
|
pN1394Params->Destination.Channel = pChannelVc->Channel;
|
|
}
|
|
|
|
//
|
|
// Make the same change for broadcast channels
|
|
//
|
|
|
|
if ((pN1394Params->Destination.Channel == NIC1394_BROADCAST_CHANNEL) &&
|
|
(pN1394Params->Destination.AddressType == NIC1394AddressType_Channel))
|
|
{
|
|
pN1394Params->Destination.Channel = pChannelVc->Channel;
|
|
}
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
//
|
|
// Time to do clean up based on what resources were allocated
|
|
//
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
//Undo all resources acquired
|
|
if (PacketPool.Handle != NULL)
|
|
{
|
|
//
|
|
// Free the pool
|
|
//
|
|
nicFreePacketPool(&PacketPool);
|
|
|
|
nicDereferenceCall ((PVCCB)pChannelVc, "nicCmMakeCallInitSendRecvChannelVc - packet pool ");
|
|
|
|
NdisZeroMemory (&pChannelVc->PacketPool, sizeof (pChannelVc->PacketPool));
|
|
}
|
|
|
|
//
|
|
// Do not decrement any ref counts because if Status != success
|
|
// then we have not incremented refcounts.
|
|
//
|
|
|
|
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallInitSendRecvChannelVc %x", NdisStatus) );
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmMakeCallInitEthernet (
|
|
IN PVCCB pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Do nothing for now. Just succeed
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
PETHERNET_VCCB pEthernetVc = (PETHERNET_VCCB)pVc;
|
|
NIC_PACKET_POOL PacketPool;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallInitEthernet %x", pVc) );
|
|
|
|
|
|
|
|
|
|
do
|
|
{
|
|
PacketPool.Handle = NULL;
|
|
|
|
//
|
|
// Initialize the PacketPool
|
|
//
|
|
|
|
NdisAllocatePacketPoolEx ( &NdisStatus,
|
|
&PacketPool.Handle,
|
|
MIN_PACKET_POOL_SIZE,
|
|
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
|
|
sizeof (RSVD) );
|
|
|
|
if (NdisStatus!= NDIS_STATUS_SUCCESS)
|
|
{
|
|
ASSERT(NdisStatus != NDIS_STATUS_SUCCESS);
|
|
pEthernetVc->PacketPool.Handle = NULL;
|
|
PacketPool.Handle = NULL;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
//
|
|
// No more failures
|
|
//
|
|
|
|
nicReferenceCall ((PVCCB)pEthernetVc, "Alloc PacketPool - Ethernet VC " ) ;
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Reference the VC as the adapter has a pointer to it
|
|
//
|
|
nicReferenceCall (pVc, "nicCmMakeCallEthernet ");
|
|
|
|
pAdapter->pEthernetVc = (PETHERNET_VCCB)pVc;
|
|
|
|
|
|
pEthernetVc->PacketPool= PacketPool;
|
|
pEthernetVc->PacketPool.AllocatedPackets = 0;
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (PacketPool.Handle != NULL)
|
|
{
|
|
//
|
|
// Free the pool
|
|
//
|
|
nicFreePacketPool(&PacketPool);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallEthernet %x", NdisStatus) );
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmMakeCallMultiChannel (
|
|
IN PVCCB pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Do whatever the channel Vc does
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
PCHANNEL_VCCB pMcVc = (PCHANNEL_VCCB)pVc;
|
|
NIC_PACKET_POOL PacketPool;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallMultiChannel %x", pVc) );
|
|
|
|
|
|
|
|
|
|
|
|
do
|
|
{
|
|
PacketPool.Handle = NULL;
|
|
|
|
|
|
//
|
|
// Initialize the PacketPool
|
|
//
|
|
|
|
NdisAllocatePacketPoolEx ( &NdisStatus,
|
|
&PacketPool.Handle,
|
|
MIN_PACKET_POOL_SIZE,
|
|
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
|
|
sizeof (RSVD) );
|
|
|
|
if (NdisStatus!= NDIS_STATUS_SUCCESS)
|
|
{
|
|
ASSERT(NdisStatus != NDIS_STATUS_SUCCESS);
|
|
pMcVc->PacketPool.Handle = NULL;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
//
|
|
// No more failures
|
|
//
|
|
|
|
nicReferenceCall ((PVCCB)pMcVc, "Alloc PacketPool - MultiChannel VC " ) ;
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
|
|
|
|
pMcVc->PacketPool= PacketPool;
|
|
pMcVc->PacketPool.AllocatedPackets = 0;
|
|
|
|
pMcVc->Hdr.MTU = pMcVc->Hdr.Nic1394MediaParams.MTU;
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
|
|
if (pMcVc->Hdr.Nic1394MediaParams.Destination.ChannnelMap.QuadPart == 0)
|
|
{
|
|
|
|
pMcVc->Channel = 0xff;
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// This portion Not Implemented yet. ChannelMap != 0
|
|
// Should use nicAllocateResourcesAndListen after updating the
|
|
// Nic1394MediaParams to make it look like a regular ChannelMake Call
|
|
//
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
ASSERT (0);
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (PacketPool.Handle != NULL)
|
|
{
|
|
//
|
|
// Free the pool
|
|
//
|
|
nicFreePacketPool(&PacketPool);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallMultiChannel %x", NdisStatus) );
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmMakeCallSendChannel (
|
|
IN PVCCB pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function allocates the channel but does nothing else.
|
|
It is only used to send data and therefore needs no other data
|
|
|
|
It needs to update pChannelVc->Channel; ulSynch; Speed;
|
|
all of which are needed to do an AsyncStream Irb
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
|
|
BOOLEAN fNeedToAllocate = VC_TEST_FLAG (pChannelVc, VCBF_NeedsToAllocateChannel);
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
ULONG Speed = 0;
|
|
UINT MaxPacketSize = 0;
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pChannelVc->Hdr.Nic1394MediaParams;
|
|
ULONG Channel = pN1394Params->Destination.Channel;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallSendChannel pVc %x", pVc) );
|
|
|
|
do
|
|
{
|
|
|
|
//
|
|
// Allocate the channel
|
|
//
|
|
if (fNeedToAllocate == TRUE)
|
|
{
|
|
|
|
NdisStatus = nicAllocateRequestedChannelMakeCallComplete (pAdapter,
|
|
pChannelVc,
|
|
&Channel);
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK (TM_Cm, ("Unable to allocate Channel on Send Only Vc" ) );
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Find out the Speed.
|
|
//
|
|
if (pAdapter->Speed == 0)
|
|
{
|
|
nicUpdateLocalHostSpeed (pAdapter);
|
|
}
|
|
|
|
|
|
pChannelVc->Speed = pAdapter->Speed;
|
|
|
|
Speed = pAdapter->Speed;
|
|
|
|
switch (pChannelVc->Speed)
|
|
{
|
|
case SPEED_FLAGS_100 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_100_RATE;
|
|
break;
|
|
}
|
|
case SPEED_FLAGS_200 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_200_RATE ;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_400 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_800:
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_1600:
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_3200 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
pChannelVc->Channel = Channel ;
|
|
|
|
MaxPacketSize = min(pN1394Params->MTU + sizeof(GASP_HEADER) , pChannelVc->Hdr.MaxPayload);
|
|
|
|
|
|
|
|
|
|
//
|
|
// If broadcast channel, then decrease the speed setting, and fragment
|
|
//
|
|
|
|
|
|
|
|
pChannelVc->Channel = Channel;
|
|
pChannelVc->MaxBufferSize = 0;
|
|
pChannelVc->Speed = Speed;
|
|
|
|
pChannelVc->Hdr.MaxPayload = MaxPacketSize;
|
|
pChannelVc->Hdr.MTU = pN1394Params->MTU ;
|
|
|
|
pChannelVc->NumDescriptors = 0;
|
|
pChannelVc->pIsochDescriptor = NULL;
|
|
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallSendChannel %x", NdisStatus) );
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicCmMakeCallCompleteFailureCleanUp(
|
|
IN OUT PVCCB pVc
|
|
)
|
|
|
|
// Function Description:
|
|
// This function cleans up, if the makecallcomplete fails for whatever reason.
|
|
// Maybe this should be split up as well
|
|
// In the RecvFIFOVc case: it needs to deallocate the Slist and PacketPool,
|
|
// Common:
|
|
// Also delete the VcType and nic1394 destination in the Vc Hdr
|
|
// Arguments
|
|
// PVCCB pVc - Vc that needs to be cleaned up
|
|
//
|
|
// Return Value:
|
|
//
|
|
//
|
|
|
|
{
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallCompleteFailureCleanUp pVc %x", pVc ) );
|
|
|
|
switch (pVc->Hdr.VcType)
|
|
{
|
|
|
|
case NIC1394_RecvFIFO:
|
|
{
|
|
PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB )pVc;
|
|
|
|
TRACE( TL_V, TM_Cm, ( "Cleaning up a recv FIFo %x", pVc ) );
|
|
|
|
if (pRecvFIFOVc->PacketPool.Handle != NULL)
|
|
{
|
|
nicFreePacketPool (&pRecvFIFOVc->PacketPool);
|
|
}
|
|
pRecvFIFOVc->PacketPool.Handle = NULL;
|
|
|
|
if (pRecvFIFOVc->FifoSListHead.Alignment != 0)
|
|
{
|
|
nicFreeAllocateAddressRangeSList (pRecvFIFOVc);
|
|
}
|
|
|
|
pRecvFIFOVc->FifoSListHead.Alignment = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
case NIC1394_SendFIFO:
|
|
case NIC1394_SendRecvChannel:
|
|
case NIC1394_SendChannel:
|
|
case NIC1394_RecvChannel:
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// This call does the generic clean up
|
|
//
|
|
nicCmGenrericMakeCallFailure (pVc);
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallCompleteFailureCleanUp ") );
|
|
|
|
MATCH_IRQL;
|
|
return ;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmCloseCall(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN PVOID CloseData,
|
|
IN UINT Size )
|
|
|
|
// Standard 'CmCloseCallHandler' routine called by NDIS when the a client
|
|
// has requested to tear down a call. See DDK doc.
|
|
//
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
ADAPTERCB* pAdapter = NULL;
|
|
VCCB* pVc = NULL;
|
|
NDIS_WORK_ITEM* pCloseCallCompleteWorkItem = NULL;
|
|
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmCloseCall($%p)", CallMgrVcContext ) );
|
|
|
|
pVc = (VCCB* )CallMgrVcContext;
|
|
|
|
if (pVc->Hdr.ulTag != MTAG_VCCB)
|
|
{
|
|
ASSERT( !"Vtag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
|
|
do
|
|
{
|
|
pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
|
|
if (pAdapter == NULL)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "pAdpater is NULL - Make Call FAILED($%p)", CallMgrVcContext ) );
|
|
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
//
|
|
// If the Make Call is Pending, then fail the CloseCall.
|
|
// Or if there call is already closing then fail this close call
|
|
//
|
|
|
|
if ( VC_ACTIVE (pVc) == FALSE )
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "NicCmCloseCall Invalid flags - Close Call FAILED Vc $%p, flags %x", pVc, pVc->Hdr.ulFlags ) );
|
|
|
|
ASSERT ( ! "MakeCallPending or Call already closed?");
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
break;
|
|
}
|
|
|
|
//
|
|
//
|
|
// Reference the Vc so we can gaurantee its presence till the end of the work item
|
|
// to CloseCallComplete. we have the lock
|
|
//
|
|
nicReferenceVc (pVc);
|
|
|
|
//
|
|
// Mark the Call as closing, and close the refcount, so no one can increment it
|
|
//
|
|
VC_SET_FLAG ( pVc, VCBF_CloseCallPending);
|
|
|
|
nicCloseCallRef (pVc);
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
pCloseCallCompleteWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
|
|
|
|
if (pCloseCallCompleteWorkItem == NULL)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem - Close Call FAILED($%p)", CallMgrVcContext ) );
|
|
|
|
NdisStatus = NDIS_STATUS_RESOURCES;
|
|
|
|
break;
|
|
}
|
|
|
|
NdisInitializeWorkItem ( pCloseCallCompleteWorkItem,
|
|
(NDIS_PROC)nicCmCloseCallComplete,
|
|
(PVOID)pVc );
|
|
|
|
NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
|
|
|
|
|
|
NdisScheduleWorkItem (pCloseCallCompleteWorkItem);
|
|
|
|
NdisStatus = NDIS_STATUS_PENDING;
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
MATCH_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmCloseCall pending" ) );
|
|
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
nicCmCloseCallComplete(
|
|
NDIS_WORK_ITEM* pCloseCallCompleteWorkItem,
|
|
IN PVOID Context
|
|
)
|
|
// Function Description:
|
|
// This function completes the close call. The qor Item gaurantees that all work will be
|
|
// done at passive level
|
|
//
|
|
// Arguments
|
|
// Context : Which is VCCB for which the close call was requested
|
|
//
|
|
//
|
|
// Return Value:
|
|
// None
|
|
// However an NdisStatus is passed in the call to Ndis' close call complete function
|
|
//
|
|
//
|
|
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PVCCB pVc = (PVCCB) Context;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
BOOLEAN fCallClosable = FALSE;
|
|
BOOLEAN fWaitSucceeded = FALSE;
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallComplete pVc %x", pVc ) );
|
|
|
|
|
|
//
|
|
// Invoke the close call handler of the VC
|
|
//
|
|
ASSERT (pVc->Hdr.VcHandlers.CloseCallHandler != NULL);
|
|
|
|
NdisStatus = (*pVc->Hdr.VcHandlers.CloseCallHandler) (pVc);
|
|
|
|
//
|
|
// right now, we do not fail a close call because the bus driver failed us.
|
|
//
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
//
|
|
// Made it so far, we now need to dereference the call. We made the reference in
|
|
// MakeCall. This will complete the call if it gets down to zero
|
|
//
|
|
if (NdisStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Derefercence the call ref and Vc Refs that were added at the end of
|
|
// a successful make call
|
|
//
|
|
nicDereferenceCall (pVc, "nicCmCloseCallComplete");
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// Important : THIS WAIT is for the REFCOUNT on the CALL , not the VC
|
|
//
|
|
TRACE( TL_N, TM_Cm, ( "About to Wait for CallRefs to go to zero pVc %x ", pVc) );
|
|
|
|
fWaitSucceeded = NdisWaitEvent (&pVc->Hdr.CallRef.RefZeroEvent, WAIT_INFINITE );
|
|
|
|
if (fWaitSucceeded == FALSE)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Wait Timed Out Call, Vc %x, RefCount %x ", pVc , pVc->Hdr.CallRef.ReferenceCount) );
|
|
|
|
ASSERT (fWaitSucceeded == TRUE);
|
|
}
|
|
|
|
|
|
ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
|
//
|
|
// Succeed the Close call as all references have gone to zero
|
|
// The call has no more outstanding resources
|
|
//
|
|
|
|
TRACE( TL_N, TM_Cm, ( "About to Close Call on pVc %x", pVc ) );
|
|
|
|
NdisMCmCloseCallComplete( NDIS_STATUS_SUCCESS,
|
|
pVc->Hdr.NdisVcHandle, NULL );
|
|
|
|
|
|
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
VC_CLEAR_FLAGS (pVc, VCBF_CloseCallPending);
|
|
VC_SET_FLAG (pVc, VCBF_CloseCallCompleted);
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
FREE_NONPAGED (pCloseCallCompleteWorkItem);
|
|
NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
|
|
|
|
//
|
|
// Release the reference made when entering the Close Call function above. so the Vc can disappear if it wants to
|
|
// Remember that delete Vc can already have gone through at this time, and the Vc will be freed after the deref
|
|
//
|
|
nicDereferenceVc (pVc);
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallComplete pVc %x, Status %x", pVc, NdisStatus ) );
|
|
|
|
MATCH_IRQL;
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmCloseCallEthernet (
|
|
IN PVCCB pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Do nothing for now. Just succeed
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
PETHERNET_VCCB pEthernetVc = (PETHERNET_VCCB)pVc;
|
|
NIC_PACKET_POOL PacketPool;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallEthernet %x", pVc) );
|
|
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
PacketPool = pEthernetVc->PacketPool;
|
|
|
|
pEthernetVc->PacketPool.Handle = 0;
|
|
pEthernetVc->PacketPool.AllocatedPackets = 0;
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
if (PacketPool.Handle != NULL)
|
|
{
|
|
nicDereferenceCall ((PVCCB)pEthernetVc, "pEthernetVc - Free PacketPool" );
|
|
nicFreePacketPool (&PacketPool);
|
|
|
|
}
|
|
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Dereference the VC as the adapter's pointer has been cleared
|
|
//
|
|
nicDereferenceCall (pVc, "nicCmMakeCallEthernet ");
|
|
|
|
pAdapter->pEthernetVc = NULL;
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
|
|
|
|
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallEthernet %x", NdisStatus) );
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmCloseCallMultiChannel (
|
|
IN PVCCB pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Free the packet pool and Just succeed
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
PCHANNEL_VCCB pMcVc = (PCHANNEL_VCCB)pVc;
|
|
NIC_PACKET_POOL PacketPool;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallMultiChannel %x", pVc) );
|
|
|
|
ASSERT (VC_TEST_FLAG (pVc, VCBF_BroadcastVc) == FALSE);
|
|
|
|
//
|
|
// Mask the fact that this is a multichannel Call
|
|
//
|
|
|
|
NdisStatus = nicCmCloseCallSendRecvChannel (pVc);
|
|
|
|
|
|
//
|
|
// Nothing to fail
|
|
//
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallMultiChannel %x", NdisStatus) );
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmCloseCallSendRecvChannel (
|
|
IN PVCCB pVc
|
|
)
|
|
// Function Description:
|
|
// This function will do clean up for RecvFifos
|
|
// Includes removing the VC pointer from Pdo Adapter structure.
|
|
// And needs to go through all active remote nodes and free the address ranges on them
|
|
// The BCM Vc has the added overhead of having an address range associated with it.
|
|
// which we need to free
|
|
//
|
|
// Arguments
|
|
// PVCCB pVc - The Channel VC that needs to be closed
|
|
//
|
|
// Return Value:
|
|
// Success for now
|
|
//
|
|
// Called with the lock held
|
|
|
|
{
|
|
PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB ) pVc;
|
|
PCHANNEL_VCCB pTempVc = NULL;
|
|
BOOLEAN fIsBroadcastVc = FALSE;
|
|
PLIST_ENTRY pVcListEntry = NULL;
|
|
PADAPTERCB pAdapter = NULL;
|
|
ULONG NumDereferenced ;
|
|
HANDLE hResource ;
|
|
ULONG NumDescriptors ;
|
|
PISOCH_DESCRIPTOR pIsochDescriptor;
|
|
BOOLEAN fAllocatedChannel ;
|
|
ULONG Channel ;
|
|
NIC_PACKET_POOL PacketPool;
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==> nicCmCloseCallSendRecvChannel pVc %x", pVc) );
|
|
|
|
ASSERT (pVc!=NULL);
|
|
pAdapter = pChannelVc->Hdr.pAF->pAdapter;
|
|
ASSERT (pAdapter != NULL);
|
|
do
|
|
{
|
|
|
|
|
|
|
|
|
|
VC_ACQUIRE_LOCK (pChannelVc);
|
|
|
|
if (VC_TEST_FLAG (pChannelVc, VCBF_BroadcastVc) == TRUE)
|
|
{
|
|
PADDRESS_RANGE_CONTEXT pBCRAddress = &pAdapter->BCRData.AddressRangeContext;
|
|
|
|
//
|
|
// Free the allocated address renge for the Broadcast Channel Register
|
|
//
|
|
if ( BCR_TEST_FLAG (pAdapter, BCR_Initialized) == TRUE)
|
|
{
|
|
|
|
//
|
|
// Clear out the Broadcast VC in the BCRData structure, Derereference the call. and clear the flag
|
|
// The ref was made in the MakeCallAllocateChannel function
|
|
//
|
|
if (pAdapter->BCRData.pBroadcastChanneVc != NULL)
|
|
{
|
|
pAdapter->BCRData.pBroadcastChanneVc = NULL;
|
|
|
|
nicDereferenceCall((PVCCB) pChannelVc, "nicCmCloseCallSendRecvChannel Broadcast VC");
|
|
}
|
|
VC_CLEAR_FLAGS (pChannelVc, VCBF_BroadcastVc) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VC_RELEASE_LOCK (pChannelVc);
|
|
|
|
nicIsochStop (pAdapter,
|
|
pChannelVc->hResource);
|
|
|
|
|
|
VC_ACQUIRE_LOCK (pChannelVc);
|
|
|
|
PacketPool = pChannelVc->PacketPool;
|
|
|
|
hResource = pChannelVc->hResource;
|
|
|
|
NumDescriptors = pChannelVc->NumDescriptors;
|
|
|
|
pIsochDescriptor = pChannelVc->pIsochDescriptor;
|
|
|
|
fAllocatedChannel = VC_TEST_FLAGS( pChannelVc, VCBF_AllocatedChannel);
|
|
|
|
Channel = pChannelVc->Channel;
|
|
|
|
PacketPool = pChannelVc->PacketPool;
|
|
|
|
//
|
|
// Clean out the VC structure and then call NDIS or the bus driver to free all
|
|
// the resources
|
|
//
|
|
nicChannelCallCleanDataStructure (pChannelVc,
|
|
pChannelVc->hResource,
|
|
pChannelVc->NumDescriptors,
|
|
pChannelVc->pIsochDescriptor,
|
|
fAllocatedChannel,
|
|
pChannelVc->Channel,
|
|
pChannelVc->PacketPool.Handle,
|
|
&NumDereferenced );
|
|
|
|
|
|
VC_RELEASE_LOCK (pChannelVc);
|
|
|
|
|
|
nicChannelCallFreeResources ( pChannelVc,
|
|
pAdapter,
|
|
hResource,
|
|
NumDescriptors,
|
|
pIsochDescriptor,
|
|
fAllocatedChannel,
|
|
Channel,
|
|
&PacketPool);
|
|
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<== nicCmCloseCallSendRecvChannel Status %x(always success)" ) );
|
|
MATCH_IRQL;
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmCloseCallRecvFIFO (
|
|
IN PVCCB pVc
|
|
)
|
|
// Function Description:
|
|
// This function will do clean up for RecvFifos
|
|
// Includes removing the VC pointer from Pdo Adapter structure.
|
|
// And needs to go through all active remote nodes and free the address ranges on them
|
|
//
|
|
//
|
|
// Arguments
|
|
// PVCCB pVc - The SendFifo that needs to be closed
|
|
//
|
|
// Return Value:
|
|
// Success for now
|
|
//
|
|
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB)pVc;
|
|
PADDRESS_FIFO pAddressFifo = NULL;
|
|
PSINGLE_LIST_ENTRY pAddressFifoEntry = NULL;
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==> nicCmCloseCallRecvFIFO pVc %x", pVc) );
|
|
|
|
NdisStatus = nicFreeAddressRange( pAdapter,
|
|
pRecvFIFOVc->AddressesReturned,
|
|
&pRecvFIFOVc->VcAddressRange,
|
|
&pRecvFIFOVc->hAddressRange );
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_I, TM_Cm, ( "Call to Free Address Range Failed pVc at %x",pVc ) );
|
|
|
|
ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
//
|
|
// Do not Break. Continue
|
|
//
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
pRecvFIFOVc->hAddressRange = NULL;
|
|
pRecvFIFOVc->AddressesReturned = 0;
|
|
pRecvFIFOVc->VcAddressRange.AR_Off_High = 0;
|
|
pRecvFIFOVc->VcAddressRange.AR_Off_Low = 0;
|
|
|
|
|
|
|
|
nicDereferenceCall ((PVCCB)pRecvFIFOVc,
|
|
"nicCmCloseCallRecvFIFO - Free address range" );
|
|
|
|
nicFreePacketPool (&pRecvFIFOVc->PacketPool);
|
|
|
|
//
|
|
// Free the Slist Entries (AddressFifo, Mdl's) and their associated memory
|
|
// and decrease the refcount for each entry
|
|
//
|
|
|
|
nicFreeAllocateAddressRangeSList (pRecvFIFOVc);
|
|
|
|
//
|
|
// At this point all the resources of the call have been exhuasted and we can del the pointer in the adapter structure
|
|
//
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
pVc->Hdr.pAF->pAdapter->pRecvFIFOVc = NULL;
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
//
|
|
// Decrement the Vc Refcount as the adapter no longer has a pointer to it
|
|
//
|
|
nicDereferenceVc (pVc);
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<== nicCmCloseCallRecvFIFO Status %x", NdisStatus) );
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmCloseCallSendFIFO (
|
|
IN PVCCB pVc
|
|
)
|
|
// Function Description:
|
|
// This function will do clean up for Send Fifos
|
|
// Includes removing the pointer to the Vc that is in Pdo Adapter structure.
|
|
// For the Send FIFO, the Pdo block is in the pVc->Hdr.pRemoteNode location, so
|
|
// this does not try and find the pRemoteNode
|
|
// Arguments
|
|
// PVCCB pVc - The SendFifo that needs to be closed
|
|
//
|
|
// Return Value:
|
|
// Success for now
|
|
//
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
REMOTE_NODE * pRemoteNode = pVc->Hdr.pRemoteNode;
|
|
PLIST_ENTRY pVcListEntry = NULL;
|
|
PSENDFIFO_VCCB pTempVc = NULL;
|
|
BOOLEAN fVcFound = FALSE;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==> nicCmCloseCallSendFIFO pVc %x", pVc) );
|
|
|
|
|
|
//
|
|
// SendComplete Handler will complete the close call.
|
|
// This thread should not do it
|
|
// Called in nicFreeSendPacketDataStructures
|
|
//
|
|
|
|
//
|
|
// Go through the PdoCb structure and remove the VC from it's VC List
|
|
//
|
|
|
|
ASSERT (pRemoteNode != NULL);
|
|
|
|
VC_ACQUIRE_LOCK (pVc);
|
|
|
|
for (pVcListEntry = pRemoteNode->VcList.Flink;
|
|
pVcListEntry != &pRemoteNode->VcList;
|
|
pVcListEntry = pVcListEntry->Flink)
|
|
{
|
|
pTempVc = (PSENDFIFO_VCCB) CONTAINING_RECORD (pVcListEntry, VCHDR, SinglePdoVcLink);
|
|
|
|
//
|
|
// Now remove the Vc from that linked list
|
|
//
|
|
if (pTempVc == (PSENDFIFO_VCCB) pVc )
|
|
{
|
|
|
|
nicRemoveEntryList (pVcListEntry);
|
|
|
|
TRACE( TL_V, TM_Cm, ( "==> Removed Vc %x From Pdo's Vc List ", pVc) );
|
|
|
|
//
|
|
// Remove the reference from the Vc as the Pdo no longer
|
|
// has a pointer to it. This ref was made in MakeCallInitSendFifo
|
|
//
|
|
nicDereferenceCall (pVc, "nicCmCloseCallSendFIFO ");
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// Decerement the Ref on the Pdo as the Vc no longer has a pointer to it.
|
|
// This Ref was made in MakeCallSendFifo function
|
|
//
|
|
|
|
nicDereferenceRemoteNode (pRemoteNode, FindRemoteNodeFromAdapter);
|
|
|
|
//
|
|
// Null, it so that if we try to access this pointer, we bugcheck
|
|
//
|
|
pVc->Hdr.pRemoteNode = NULL;
|
|
|
|
VC_RELEASE_LOCK (pVc);
|
|
|
|
//
|
|
// There is no reason why we should not have found the Vc in the Pdo list
|
|
//
|
|
ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<== nicCmCloseCallSendFIFO Status %x", NdisStatus) );
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmCloseCallSendChannel(
|
|
IN PVCCB pVc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free the channel, if its been allocated
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PADAPTERCB pAdapter = (PADAPTERCB) pVc->Hdr.pAF->pAdapter;
|
|
PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallSendChannel " ) );
|
|
|
|
if (VC_TEST_FLAG (pVc,VCBF_AllocatedChannel) == TRUE)
|
|
{
|
|
nicFreeChannel (pAdapter, pChannelVc->Channel);
|
|
nicDereferenceCall ((PVCCB)pChannelVc, "Close Call - Send Channel - Freeing Channel" );
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallSendChannel " ) );
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicChannelCallFreeResources (
|
|
IN PCHANNEL_VCCB pChannelVc,
|
|
IN PADAPTERCB pAdapter,
|
|
IN HANDLE hResource,
|
|
IN ULONG NumDescriptors,
|
|
IN PISOCH_DESCRIPTOR pIsochDescriptor,
|
|
IN BOOLEAN fChannelAllocated,
|
|
IN ULONG Channel,
|
|
IN PNIC_PACKET_POOL pPacketPool
|
|
|
|
)
|
|
// Function Description:
|
|
// This function is called from Close call or MakeCall Failure code path.
|
|
// It will detach buffers, free resources, free channel and free bandwdith.
|
|
// It is the responsibility of the caller to do all the appropriate ref counting
|
|
//
|
|
// Arguments
|
|
//
|
|
// pAdapter contains the VDO to which all the IRPs were sent
|
|
// hResource resource handle to be used by the bus driver,
|
|
// NumDescriptors Number of descriptors attached to the buffer,
|
|
// pIsochDesciptor Original pointer to the start of the Buffer Descriptor ,
|
|
// Channel, - Channel that was allocated
|
|
//
|
|
// Return Value:
|
|
// Success if all irps completed succeesfully. Wil be ignored by called
|
|
//
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
STORE_CURRENT_IRQL;
|
|
TRACE( TL_T, TM_Cm, ( "==>nicChannelCallFreeResources " ) );
|
|
TRACE( TL_V, TM_Cm, ( "hResource %x, NumDescriptors %.2x, pIsochDescriptor %x, Channel Allocated %.2x, Channel %x",
|
|
hResource, NumDescriptors, pIsochDescriptor, fChannelAllocated, Channel ) )
|
|
|
|
//
|
|
// Reference the pdo structure so it will be around until the end
|
|
// of this function
|
|
// Reference decremented at the end of this function
|
|
//
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
nicReferenceAdapter (pAdapter, "nicChannelCallFreeResources ");
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Do not break out of the loop. We need to try and free as much as possible
|
|
//
|
|
|
|
if (pIsochDescriptor != NULL)
|
|
{
|
|
// Detach Buffers
|
|
//
|
|
while (pChannelVc->NumIndicatedIsochDesc != 0 )
|
|
{
|
|
//
|
|
// we will wait for ever, checking periodically for all the packets to return
|
|
//
|
|
TRACE( TL_V, TM_Cm, ( " nicChannelCallFreeResources - Sleeping to wait for packets to be retuerned " ) );
|
|
|
|
NdisMSleep ( FIFTY_MILLISECONDS );
|
|
|
|
}
|
|
|
|
NdisStatus = nicIsochDetachBuffers( pAdapter,
|
|
hResource,
|
|
NumDescriptors,
|
|
pIsochDescriptor );
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "nicIsochDetachBuffers FAILED " ) );
|
|
ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
// First Free Isoch Descriptors and their associated MDLs
|
|
//
|
|
nicFreeIsochDescriptors (NumDescriptors, pIsochDescriptor, (PVCCB)pChannelVc);
|
|
}
|
|
|
|
if (hResource != NULL)
|
|
{
|
|
|
|
// Free resources
|
|
//
|
|
NdisStatus = nicIsochFreeResources( pAdapter,
|
|
hResource );
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "nicIsochFreeResources FAILED " ) );
|
|
ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if (fChannelAllocated == TRUE)
|
|
{
|
|
PULONGLONG pLocalHostChannels = &pAdapter->ChannelsAllocatedByLocalHost;
|
|
|
|
ASSERT (Channel < NIC1394_MAX_NUMBER_CHANNELS);
|
|
|
|
// Free the Channel
|
|
//
|
|
|
|
NdisStatus = nicFreeChannel (pAdapter,
|
|
Channel);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "nicIsochFreeChannel FAILED " ) );
|
|
ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
//
|
|
// Clear the bit in the adapter;s channel bitmap
|
|
//
|
|
VC_ACQUIRE_LOCK (pChannelVc);
|
|
|
|
(*pLocalHostChannels)= ((*pLocalHostChannels) & (~(g_ullOne <<Channel)));
|
|
|
|
|
|
VC_CLEAR_FLAGS( pChannelVc, VCBF_AllocatedChannel);
|
|
|
|
VC_RELEASE_LOCK (pChannelVc);
|
|
|
|
|
|
|
|
}
|
|
|
|
if (pPacketPool->Handle != NULL)
|
|
{
|
|
nicFreePacketPool(pPacketPool);
|
|
}
|
|
|
|
//
|
|
// Remove The Ref that was added in the beginning of the function
|
|
//
|
|
|
|
nicDereferenceAdapter (pAdapter, "nicChannelCallFreeResources ");
|
|
|
|
|
|
MATCH_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicChannelCallFreeResources " ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicChannelCallCleanDataStructure (
|
|
IN PCHANNEL_VCCB pChannelVc,
|
|
IN HANDLE hResource,
|
|
IN ULONG NumDescriptors,
|
|
IN PISOCH_DESCRIPTOR pIsochDescriptor,
|
|
IN BOOLEAN fChannelAllocated,
|
|
IN ULONG Channel,
|
|
IN NDIS_HANDLE hPacketPoolHandle,
|
|
OUT PULONG pNumRefsDecremented
|
|
)
|
|
// Function Description:
|
|
// If any of the data fields in the ChannelVc match the
|
|
// corresponding argument in this structure it will be
|
|
// NULLed out and the call dereferenced
|
|
//
|
|
// Called with the lock held.
|
|
//
|
|
// Arguments
|
|
// PCHANNEL_VCCB pChannelVc, - Channel Vc
|
|
// HANDLE hResource, - Handle to resource
|
|
// ULONG NumDescriptors, - Num descriptors will be set to zero
|
|
// PISOCH_DESCRIPTOR pIsochDesciptor, - Pointer to array of isoch descriptors
|
|
// BOOLEAN fChannelAllocated, - Was the Channel allocated
|
|
// ULONG Channel, - channel number
|
|
// NDIS_HANDLE hPacketPoolHandle - Packet pool handle
|
|
//
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
//
|
|
//
|
|
//
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
ULONG NumRefsDecremented = 0;
|
|
TRACE( TL_T, TM_Cm, ( "==>nicChannelCallCleanDataStructure " ) );
|
|
|
|
TRACE( TL_V, TM_Cm, ( "hResource %x, NumDescriptors %.2x, pIsochDescriptor %x, Channel Allocated %.2x, Channel %x",
|
|
hResource, NumDescriptors, pIsochDescriptor, fChannelAllocated, Channel ) )
|
|
|
|
if (pChannelVc == NULL)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
if ((pChannelVc->NumDescriptors == NumDescriptors )&&
|
|
(pChannelVc->pIsochDescriptor == pIsochDescriptor ) &&
|
|
pIsochDescriptor != NULL )
|
|
{
|
|
pChannelVc->NumDescriptors = 0;
|
|
pChannelVc->pIsochDescriptor = NULL;
|
|
nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure Detach Buffers ");
|
|
NumRefsDecremented ++;
|
|
}
|
|
|
|
if (hResource != NULL && pChannelVc->hResource == hResource)
|
|
{
|
|
pChannelVc->hResource = NULL;
|
|
nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure Free Resource ");
|
|
NumRefsDecremented ++;
|
|
}
|
|
|
|
|
|
if (fChannelAllocated == TRUE)
|
|
{
|
|
ASSERT ( VC_TEST_FLAG (pChannelVc, VCBF_AllocatedChannel) == TRUE);
|
|
VC_CLEAR_FLAGS (pChannelVc, VCBF_AllocatedChannel);
|
|
|
|
pChannelVc->Channel = INVALID_CHANNEL;
|
|
|
|
nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure - Free Channel");
|
|
NumRefsDecremented ++;
|
|
|
|
}
|
|
|
|
if (hPacketPoolHandle != NULL && pChannelVc->PacketPool.Handle == hPacketPoolHandle)
|
|
{
|
|
pChannelVc->PacketPool.Handle = NULL;
|
|
nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure - Packet Pool");
|
|
NumRefsDecremented ++;
|
|
}
|
|
|
|
|
|
|
|
//REMOTE_NODE_RELEASE_LOCK (pRemoteNodePdoCb);
|
|
|
|
//
|
|
// Remove The Ref that was added in the beginning of the function
|
|
//
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
if (pNumRefsDecremented != NULL)
|
|
{
|
|
*pNumRefsDecremented = NumRefsDecremented ;
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicChannelCallCleanDataStructure %x", *pNumRefsDecremented ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmModifyCallQoS(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN PCO_CALL_PARAMETERS CallParameters )
|
|
|
|
// Standard 'CmModifyQoSCallHandler' routine called by NDIS when a client
|
|
// requests a modification in the quality of service provided by the
|
|
// virtual circuit. See DDK doc.
|
|
//
|
|
{
|
|
TRACE( TL_T, TM_Cm, ( "NicCmModQoS" ) );
|
|
|
|
// There is no useful concept of quality of service for IP media.
|
|
//
|
|
return NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
NicCmRequest(
|
|
IN NDIS_HANDLE CallMgrAfContext,
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN OUT PNDIS_REQUEST pNdisRequest )
|
|
|
|
// Standard 'CmRequestHandler' routine called by NDIS in response to a
|
|
// client's request for information from the call manager.
|
|
//
|
|
{
|
|
AFCB* pAF;
|
|
VCCB* pVc;
|
|
NDIS_STATUS NdisStatus;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmReq" ) );
|
|
|
|
pAF = (AFCB*) CallMgrAfContext;
|
|
|
|
if (pAF->ulTag != MTAG_AFCB )
|
|
{
|
|
ASSERT( !"Atag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
pVc = (VCCB* )CallMgrVcContext;
|
|
|
|
if (pVc && pVc->Hdr.ulTag != MTAG_VCCB)
|
|
{
|
|
ASSERT( !"Vtag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
#if TODO // Add 1394-specific functionality here.
|
|
#endif
|
|
ASSERT(pNdisRequest != NULL);
|
|
|
|
switch (pNdisRequest->RequestType)
|
|
{
|
|
case NdisRequestQueryStatistics:
|
|
case NdisRequestQueryInformation:
|
|
|
|
{
|
|
NdisStatus = nicCmQueryInformation(
|
|
CallMgrAfContext,
|
|
CallMgrVcContext,
|
|
CallMgrPartyContext,
|
|
pNdisRequest->DATA.QUERY_INFORMATION.Oid,
|
|
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
|
|
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
|
|
&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
|
|
&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded );
|
|
break;
|
|
}
|
|
|
|
case NdisRequestSetInformation:
|
|
{
|
|
|
|
NdisStatus = nicCmSetInformation(
|
|
CallMgrAfContext,
|
|
CallMgrVcContext,
|
|
CallMgrPartyContext,
|
|
pNdisRequest->DATA.SET_INFORMATION.Oid,
|
|
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,
|
|
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
|
|
&pNdisRequest->DATA.SET_INFORMATION.BytesRead,
|
|
&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded );
|
|
break;
|
|
}
|
|
|
|
|
|
default:
|
|
{
|
|
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
|
|
TRACE( TL_A, TM_Mp, ( "type=%d?", pNdisRequest->RequestType ) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmReq" ) );
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
nicDereferenceAF(
|
|
IN AFCB* pAF )
|
|
|
|
// Removes a reference from the address family of adapter control block
|
|
// 'pAdapter', and when frees the block when the last reference is
|
|
// removed.
|
|
//
|
|
{
|
|
LONG lRef;
|
|
|
|
lRef = NdisInterlockedDecrement (&pAF->lRef);
|
|
|
|
TRACE( TL_T, TM_Ref, ( "DerefAf to %d", lRef ) );
|
|
ASSERT( lRef >= 0 );
|
|
|
|
if (lRef == 0)
|
|
{
|
|
ADAPTERCB* pAdapter = pAF->pAdapter;
|
|
|
|
// Remove linkages.
|
|
//
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
pAF->pAdapter = NULL;
|
|
|
|
nicRemoveEntryList (&pAF->linkAFCB);
|
|
|
|
InitializeListHead (&pAF->linkAFCB);
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
// Tell NDIS it's close is complete.
|
|
//
|
|
|
|
ASSERT ( nicReadFlags (&pAF->ulFlags) & ACBF_ClosePending);
|
|
|
|
TRACE( TL_I, TM_Cm, ( "NdisMCmCloseAfComp Af %x",pAF ) );
|
|
|
|
NdisMCmCloseAddressFamilyComplete(
|
|
NDIS_STATUS_SUCCESS, pAF->NdisAfHandle );
|
|
|
|
//
|
|
// Update State information to show that we have called CloseComplete
|
|
//
|
|
nicSetFlags ( &pAF->ulFlags, ACBF_CloseComplete);
|
|
nicClearFlags ( &pAF->ulFlags, ACBF_ClosePending);
|
|
|
|
nicDereferenceAdapter (pAdapter, "NdisMCmCloseAfComp "); // nicDereferenceFA (CloseAfComp)
|
|
|
|
nicFreeAF (pAF);
|
|
|
|
TRACE( TL_I, TM_Cm, ( "NdisMCmCloseAfComp done Af %x", pAF ) );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
nicDereferenceCall(
|
|
IN VCCB* pVc,
|
|
IN PCHAR pDebugPrint
|
|
)
|
|
|
|
// Removes a reference from the call active on 'pVc', invoking call clean
|
|
// up when the value reaches zero.
|
|
//
|
|
// CAlled with the lock held
|
|
{
|
|
BOOLEAN bRefZero = FALSE;
|
|
LONG RefCount;
|
|
//
|
|
// If the Ref goes to zero, derefref return true
|
|
//
|
|
|
|
|
|
bRefZero = nicDereferenceRef (&pVc->Hdr.CallRef, &RefCount);
|
|
|
|
TRACE( TL_V, TM_Ref, ( "***DerefCall %x to %d , %s" , pVc, RefCount, pDebugPrint ) );
|
|
|
|
if ( bRefZero == TRUE)
|
|
{
|
|
//
|
|
// Dereference the Vc as the Call no longer exists. This reference was
|
|
// added in the beginning of the make call
|
|
nicDereferenceVc (pVc);
|
|
|
|
}
|
|
|
|
return bRefZero;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
nicDereferenceVc(
|
|
IN VCCB* pVc )
|
|
|
|
// Removes a reference to the VC control block 'pVc', and when frees the
|
|
// block when the last reference is removed.
|
|
//
|
|
{
|
|
LONG lRef;
|
|
|
|
lRef = NdisInterlockedDecrement( &pVc->Hdr.lRef );
|
|
|
|
TRACE( TL_V, TM_Ref, ( "DerefVC to %d", lRef ) );
|
|
ASSERT( lRef >= 0 );
|
|
|
|
if (lRef == 0 )
|
|
{
|
|
// If close call is pending and the refcount has gone to zero, then call
|
|
//
|
|
|
|
ASSERT( pVc->Hdr.ulTag == MTAG_VCCB );
|
|
|
|
pVc->Hdr.ulTag = MTAG_FREED;
|
|
|
|
FREE_VCCB( pAdapter, pVc );
|
|
|
|
TRACE( TL_I, TM_Mp, ( "VCB freed $%p", pVc ) );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
nicFreeAF(
|
|
IN AFCB* pAF )
|
|
|
|
// Frees all resources allocated for address family 'pAF', including
|
|
// 'pAF' itself.
|
|
//
|
|
{
|
|
|
|
#if TODO
|
|
Assert that the various lists (such as pAF->AFVCList) and resources are empty.
|
|
#endif // TODO
|
|
|
|
pAF->ulTag = MTAG_FREED;
|
|
|
|
FREE_NONPAGED (pAF);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
nicReferenceAF(
|
|
IN AFCB* pAF )
|
|
|
|
// Adds areference to the address family of adapter block, 'pAdapter'.
|
|
//
|
|
{
|
|
LONG lRef=0;
|
|
|
|
lRef = NdisInterlockedIncrement (&pAF->lRef);
|
|
|
|
TRACE( TL_V, TM_Ref, ( "RefAf to %d", lRef ) );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
nicReferenceCall(
|
|
IN VCCB* pVc,
|
|
IN PCHAR pDebugPrint
|
|
)
|
|
|
|
// Returns true if a reference is added to the active call on VC control
|
|
// block, 'pVc', or false if no reference was added because no call is
|
|
// active.
|
|
//
|
|
{
|
|
BOOLEAN fActive;
|
|
LONG RefNumber;
|
|
|
|
|
|
fActive = nicReferenceRef (&pVc->Hdr.CallRef, &RefNumber);
|
|
|
|
TRACE( TL_V, TM_Ref, ( "***RefCall %x to %d , %s" , pVc, pVc->Hdr.CallRef.ReferenceCount, pDebugPrint ) );
|
|
|
|
if ( fActive==FALSE)
|
|
{
|
|
TRACE( TL_N, TM_Ref, ( "RefC Inactive" ) );
|
|
}
|
|
|
|
return fActive;
|
|
}
|
|
|
|
|
|
VOID
|
|
nicReferenceVc(
|
|
IN VCCB* pVc )
|
|
|
|
// Adds a reference to the VC control block 'pVc'.
|
|
//
|
|
{
|
|
LONG lRef;
|
|
|
|
lRef = NdisInterlockedIncrement (&pVc->Hdr.lRef);
|
|
|
|
TRACE( TL_I, TM_Ref, ( "RefVc to %d", lRef ) );
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
nicAllocateRequestedChannelMakeCallComplete (
|
|
IN PADAPTERCB pAdapter,
|
|
IN PCHANNEL_VCCB pChannelVc,
|
|
IN OUT PULONG pChannel
|
|
)
|
|
// Function Description:
|
|
// This function allocates the channel requested in the make
|
|
// If any channel is requested it will try all 64.
|
|
// If the broadcast channel is requested, it will look for
|
|
// for the channel allocated by the BCM
|
|
// Other wise it will simply try and allocate the requested channel
|
|
//
|
|
// This can be called from the AddFirstRemoteNode code path.
|
|
//
|
|
// Arguments
|
|
// Channel Vc - The channel Vc in question
|
|
// Channel - the channel requested
|
|
//
|
|
// Return Value:
|
|
// Success : if allocate channel succeeds
|
|
// pChannel - contains the allocated channel
|
|
//
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
ULONG Channel = *pChannel;
|
|
BOOLEAN fAnyChannel = FALSE;
|
|
BOOLEAN fFailCall = FALSE;
|
|
|
|
TRACE( TL_T, TM_Cm, ( " ==>nicAllocateRequestedChannelMakeCallComplete pAdapter, pVc %x, Channel %x ",
|
|
pAdapter, pChannelVc, *pChannel ) );
|
|
|
|
do
|
|
{
|
|
|
|
//
|
|
// First make sure we have a good channel number
|
|
//
|
|
|
|
if ( (signed long)Channel < (signed long)NIC1394_BROADCAST_CHANNEL ||
|
|
(signed long)Channel >(signed long)MAX_CHANNEL_NUMBER)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Invalid Channel Number, channel %x", Channel) );
|
|
|
|
NdisStatus = NDIS_STATUS_INVALID_DATA;
|
|
|
|
ASSERT (!(signed long)Channel < (signed long)NIC1394_BROADCAST_CHANNEL ||
|
|
(signed long)Channel >(signed long)MAX_CHANNEL_NUMBER);
|
|
|
|
break;
|
|
}
|
|
|
|
if ((signed long)Channel == NIC1394_BROADCAST_CHANNEL )
|
|
{
|
|
NETWORK_CHANNELSR* pBCR;
|
|
ULONG i = 0;
|
|
|
|
pBCR = &pAdapter->BCRData.IRM_BCR;
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
if (BCR_IS_VALID (pBCR) == FALSE)
|
|
{
|
|
BOOLEAN bWaitSuccessful = FALSE;
|
|
BOOLEAN fIsTheBCRFree = FALSE;
|
|
//
|
|
// BCM algorithm has not completed yet, we need to wait
|
|
//
|
|
TRACE( TL_I, TM_Cm, ( " nicAllocateRequestedChannelMakeCallComplete : BCR Has not completed. About to wait BCR %x ", *pBCR ) );
|
|
|
|
|
|
BCR_SET_FLAG (pAdapter, BCR_MakeCallPending);
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
//
|
|
// If we don't have a BCR then we should wait until the BCM algorithm completes
|
|
//
|
|
|
|
//
|
|
// Now wait for the BCM algorithm to complete. First we will wait for
|
|
// 5 seconds. (5*1)
|
|
// If we still don't see it, we will reset the bus and hope that the new
|
|
// iteration of BCM will succeed.
|
|
//
|
|
|
|
|
|
//
|
|
// There can 2 reasons to stop waiting, the BCR is being freed because of a
|
|
// standby or BCR is correct. We check both conditions
|
|
//
|
|
|
|
NdisWaitEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent, (5000));
|
|
|
|
//
|
|
// We reset the bus - if the BCR is not getting freed and we
|
|
// still do not have a valid BCR . and than we wait
|
|
// for the BCR to complete
|
|
//
|
|
if (BCR_IS_VALID(pBCR) == FALSE &&
|
|
(BCR_TEST_FLAGS (pAdapter, BCR_BCRNeedsToBeFreed | BCR_Freed)== FALSE))
|
|
{
|
|
TRACE( TL_I, TM_Cm, ( " nicAllocateRequestedChannelMakeCallComplete WaitCompleted - About to RESET THE BUS" ) );
|
|
nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
|
|
|
|
//
|
|
// Wait for 5 minutes before failing the Make Call
|
|
// (5 minutes is an experimental number)
|
|
//
|
|
{
|
|
BOOLEAN bWait;
|
|
|
|
bWait = NdisWaitEvent (
|
|
&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent,
|
|
ONE_MINUTE * 5 );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
NdisResetEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
|
|
|
|
pAdapter->BCRData.MakeCallWaitEvent.EventCode = Nic1394EventCode_InvalidEventCode;
|
|
BCR_CLEAR_FLAG (pAdapter, BCR_MakeCallPending);
|
|
|
|
|
|
//
|
|
// if we have not got a valid BCR, then fail the call
|
|
//
|
|
if (BCR_IS_VALID(pBCR) == FALSE ||
|
|
BCR_TEST_FLAGS (pAdapter, BCR_BCRNeedsToBeFreed | BCR_Freed))
|
|
{
|
|
fFailCall = TRUE;
|
|
ADAPTER_RELEASE_LOCK(pAdapter);
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Channel = pBCR->NC_Channel;
|
|
|
|
//
|
|
// Update the VC structure and break .
|
|
// Do not add a reference. Do not set the flag
|
|
//
|
|
|
|
pChannelVc->Channel = Channel;
|
|
|
|
pChannelVc->Hdr.Nic1394MediaParams.Destination.Channel = Channel;
|
|
|
|
//
|
|
// Reference that this Vc now has a pointer in the BCRData. This is dereferneced
|
|
// in the channel close call complete.
|
|
//
|
|
nicReferenceCall ((PVCCB)pChannelVc, "nicAllocateRequestedChannelMakeCallComplete Broadcast VC");
|
|
|
|
pAdapter->BCRData.pBroadcastChanneVc = pChannelVc;
|
|
|
|
|
|
VC_SET_FLAG (pChannelVc, VCBF_BroadcastVc);
|
|
|
|
pAdapter->ChannelsAllocatedByLocalHost = pAdapter->ChannelsAllocatedByLocalHost | (g_ullOne<<Channel);
|
|
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
if ((signed long)Channel == NIC1394_ANY_CHANNEL )
|
|
{
|
|
TRACE( TL_V, TM_Cm, ( "Requesting Any Channel %x", Channel) );
|
|
|
|
fAnyChannel = TRUE;
|
|
Channel = MAX_CHANNEL_NUMBER;
|
|
}
|
|
|
|
//
|
|
// Now begin the request to allocate a channel
|
|
//
|
|
if (fAnyChannel == FALSE)
|
|
{
|
|
TRACE( TL_V, TM_Cm, ( "Requesting Channel %x, on remote node ", Channel ) );
|
|
|
|
|
|
NdisStatus = nicAllocateChannel ( pAdapter,
|
|
Channel,
|
|
NULL);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
//
|
|
// we need to go through all 64 channels.
|
|
//
|
|
do
|
|
{
|
|
|
|
NdisStatus = nicAllocateChannel ( pAdapter,
|
|
Channel,
|
|
NULL);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (Channel == 0 )
|
|
{
|
|
//
|
|
// We now need to fail the make call as the user asked for any channel
|
|
// and none are available
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
Channel --;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We succeeded in allocating a channel .. break
|
|
//
|
|
break;
|
|
}
|
|
|
|
} while (TRUE);
|
|
|
|
}
|
|
|
|
//
|
|
// Status of Channel allocation. If AnyChannel == TRUE then we need to make sure that
|
|
// a channel was allocated
|
|
//
|
|
if (NdisStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
|
|
VC_ACQUIRE_LOCK (pChannelVc);
|
|
|
|
VC_SET_FLAG( pChannelVc, VCBF_AllocatedChannel);
|
|
|
|
pChannelVc->Channel = Channel;
|
|
|
|
pChannelVc->Hdr.Nic1394MediaParams.Destination.Channel = Channel;
|
|
|
|
//
|
|
// Record the channel number in the adpater structure
|
|
//
|
|
pAdapter->ChannelsAllocatedByLocalHost = pAdapter->ChannelsAllocatedByLocalHost | (g_ullOne<<Channel);
|
|
|
|
VC_RELEASE_LOCK (pChannelVc);
|
|
|
|
nicReferenceCall ((PVCCB)pChannelVc, "nicAllocateRequestedChannelMakeCallComplete -Allocated Channel");
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// we failed to allocate any channel and are going to fail
|
|
//
|
|
if (fAnyChannel == TRUE)
|
|
{
|
|
Channel = 0xff;
|
|
NdisStatus = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// If the Call specifically wants the channel to
|
|
// be allocated, we return the correct channel allocate
|
|
// status to it,
|
|
//
|
|
// Otherwise we overwrite and presume that another node may
|
|
// already have allocated the channel
|
|
//
|
|
if (VC_TEST_FLAG (pChannelVc,VCBF_NeedsToAllocateChannel) == FALSE)
|
|
{
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
ASSERT (!"Failing make call because channel was allocated, Hit 'g'");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
*pChannel = Channel;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicAllocateRequestedChannelMakeCallComplete Status %x Channel %x", NdisStatus, *pChannel ) );
|
|
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicFindRemoteNodeFromAdapter(
|
|
IN PADAPTERCB pAdapter,
|
|
IN PDEVICE_OBJECT pRemotePdo,
|
|
IN UINT64 UniqueId,
|
|
IN OUT REMOTE_NODE ** ppRemoteNode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine matches either a Remote Node' pdo OR unique
|
|
Id to the Remote node's on the adapter
|
|
|
|
It walks the RemoteNode List in the Adapter Structure
|
|
and tries to find a match for the Unique Id,
|
|
or match the remote Pdo from the adapter's PdoList
|
|
|
|
|
|
Arguments:
|
|
pAdapter - pAdapter on which to search
|
|
pRemoptePdo - Remote Pdo to find
|
|
UniqueId - Unique Id to find
|
|
ppRemoteNode - Remote Node structure
|
|
|
|
Return Value:
|
|
Success if the node is found
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PLIST_ENTRY pPdoListEntry = NULL;
|
|
PREMOTE_NODE pRemoteNode = NULL;
|
|
BOOLEAN fPdoFound = FALSE;
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicFindRemoteNodeFromAdapter pAdapter is %x, ,Pdo %x, UniqueId %I64x ", pAdapter, pRemotePdo, UniqueId ) );
|
|
|
|
//
|
|
// Validate the parameters
|
|
//
|
|
ASSERT (pAdapter != NULL);
|
|
TRACE( TL_I, TM_Cm, ( " Request to Match UniqueID %I64x or pRemotePdo %x", UniqueId, pRemotePdo) );
|
|
|
|
|
|
do
|
|
{
|
|
(*ppRemoteNode) = NULL;
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
//
|
|
// Check for empty list
|
|
//
|
|
if (pAdapter->PDOList.Flink == &pAdapter->PDOList)
|
|
{
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
MATCH_IRQL;
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
(*ppRemoteNode) = NULL;
|
|
TRACE( TL_A, TM_Cm, ( " NO REMOTE NODES PRESENT FAILING MAKE CALL ") );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// go through all the Pdo's on the adapter
|
|
//
|
|
for (pPdoListEntry = pAdapter->PDOList.Flink;
|
|
pPdoListEntry!= &pAdapter->PDOList;
|
|
pPdoListEntry = pPdoListEntry->Flink)
|
|
{
|
|
pRemoteNode = CONTAINING_RECORD( pPdoListEntry,
|
|
REMOTE_NODE,
|
|
linkPdo);
|
|
|
|
//
|
|
// Check for the two cases, i.e unique Id's match or Pdo's match
|
|
//
|
|
if ( pRemoteNode->UniqueId == UniqueId || pRemoteNode->pPdo == pRemotePdo)
|
|
{
|
|
TRACE( TL_I, TM_Cm, ( " Matched UniqueID or pRemotePdo for Pdo%x",pRemoteNode->pPdo) );
|
|
|
|
*ppRemoteNode = pRemoteNode;
|
|
nicReferenceRemoteNode (pRemoteNode, FindRemoteNodeFromAdapter);
|
|
//
|
|
// We ref pRemoteNode to keep it alive once we release the lock.
|
|
// Caller is responsible for derefing pRemoteNode.
|
|
//
|
|
|
|
fPdoFound = TRUE;
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "remote node's Unique ID's %I64x, given UniqueID %I64x ", pRemoteNode->UniqueId, UniqueId ) );
|
|
}
|
|
|
|
|
|
}
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
MATCH_IRQL;
|
|
|
|
TRACE( TL_V, TM_Cm, ( "Is PdoFound %.2x, RemoteNode at %x ", fPdoFound, &fPdoFound ) );
|
|
|
|
if (fPdoFound ==FALSE)
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Remote Node was NOT Found: Make Call failed " ) );
|
|
ASSERT ((*ppRemoteNode) == NULL);
|
|
}
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicFindRemoteNodeFromAdapter pPdoBlock %x",(*ppRemoteNode) ) );
|
|
|
|
MATCH_IRQL;
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmQueryInformation(
|
|
IN NDIS_HANDLE CallMgrAfContext,
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesWritten,
|
|
OUT PULONG BytesNeeded
|
|
)
|
|
|
|
// Handle QueryInformation requests. Arguments are as for the standard
|
|
// NDIS 'CallMgrQueryInformation' handler except this routine does not
|
|
// count on being serialized with respect to other requests.
|
|
//
|
|
{
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS NdisStatus;
|
|
ULONG ulInfo;
|
|
VOID* pInfo;
|
|
ULONG ulInfoLen;
|
|
USHORT usInfo;
|
|
|
|
// The next variables are used to setup the data structures that are
|
|
// used to respond to the OIDs they correspond to
|
|
//
|
|
|
|
|
|
NDIS_CO_LINK_SPEED CoLinkSpeed;
|
|
NIC1394_LOCAL_NODE_INFO LocalNodeInfo;
|
|
NIC1394_VC_INFO VcInfo;
|
|
PVCCB pVc;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>nicCmQueryInformation %x, Vc %x", Oid, CallMgrVcContext ) );
|
|
|
|
|
|
// The cases in this switch statement find or create a buffer containing
|
|
// the requested information and point 'pInfo' at it, noting it's length
|
|
// in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
|
|
// buffer is set up as the default.
|
|
//
|
|
ulInfo = 0;
|
|
pInfo = &ulInfo;
|
|
ulInfoLen = sizeof (ulInfo);
|
|
|
|
NdisStatus = NDIS_STATUS_SUCCESS;
|
|
|
|
// Validate the arguments
|
|
//
|
|
pVc = (VCCB* )CallMgrVcContext;
|
|
|
|
if (pVc && pVc->Hdr.ulTag != MTAG_VCCB)
|
|
{
|
|
ASSERT( !"Vtag?" );
|
|
return NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
|
|
// Perform the request
|
|
//
|
|
switch (Oid)
|
|
{
|
|
|
|
case OID_1394_VC_INFO:
|
|
{
|
|
|
|
// Returns information about the VC that is being queried
|
|
//
|
|
|
|
|
|
TRACE( TL_N, TM_Mp, ("QInfo(OID_1394_VC_INFO)") );
|
|
|
|
VcInfo.Destination = pVc->Hdr.Nic1394MediaParams.Destination;
|
|
|
|
pInfo = &VcInfo;
|
|
|
|
ulInfoLen = sizeof (VcInfo);
|
|
|
|
break;
|
|
}
|
|
|
|
case OID_1394_ISSUE_BUS_RESET:
|
|
{
|
|
PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
|
|
|
|
TRACE( TL_V, TM_Mp, ( " OID_1394_ISSUE_BUS_RESET" ) );
|
|
|
|
if (InformationBufferLength == sizeof(ULONG))
|
|
{
|
|
nicIssueBusReset (pAdapter, (*(PULONG)InformationBuffer));
|
|
}
|
|
else
|
|
{
|
|
nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
TRACE( TL_A, TM_Cm, ( "Q-OID=$%08x?", Oid ) );
|
|
NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
|
|
ulInfoLen = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ulInfoLen > InformationBufferLength)
|
|
{
|
|
// Caller's buffer is too small. Tell him what he needs.
|
|
//
|
|
*BytesNeeded = ulInfoLen;
|
|
*BytesWritten = 0;
|
|
|
|
NdisStatus = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
// Copy the found result to caller's buffer.
|
|
//
|
|
if (ulInfoLen > 0)
|
|
{
|
|
NdisMoveMemory (InformationBuffer, pInfo, ulInfoLen );
|
|
|
|
DUMPDW( TL_N, TM_Mp, pInfo, ulInfoLen );
|
|
}
|
|
|
|
*BytesNeeded = *BytesWritten = ulInfoLen;
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicCmQueryInformation %x",NdisStatus ) );
|
|
|
|
return NdisStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmSetInformation(
|
|
IN NDIS_HANDLE CallMgrAfContext,
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesRead,
|
|
OUT PULONG BytesNeeded
|
|
)
|
|
//
|
|
// Not implemented yet. Will be used to set information
|
|
//
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
|
|
PVCCB pVc;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallInitVc Oid %x",Oid ) );
|
|
|
|
// Validate the arguments
|
|
//
|
|
UNREFERENCED_PARAMETER(CallMgrAfContext);
|
|
UNREFERENCED_PARAMETER(CallMgrVcContext);
|
|
UNREFERENCED_PARAMETER(CallMgrAfContext);
|
|
UNREFERENCED_PARAMETER(CallMgrPartyContext);
|
|
UNREFERENCED_PARAMETER(Oid);
|
|
UNREFERENCED_PARAMETER(InformationBuffer);
|
|
UNREFERENCED_PARAMETER(InformationBufferLength);
|
|
UNREFERENCED_PARAMETER(BytesRead);
|
|
UNREFERENCED_PARAMETER(BytesNeeded);
|
|
TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallInitVc %x",NdisStatus ) );
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicInitRecvFifoDataStructures (
|
|
IN PRECVFIFO_VCCB pRecvFIFOVc
|
|
)
|
|
|
|
// Function Description:
|
|
// This function will initialize the data structures, buffers etc that are needed on
|
|
// all the allocate address range Irps that will be called because of the RecvFifo Vc
|
|
//
|
|
// Arguments
|
|
// pRecvFIFOVc - RecvFifo Vc structure
|
|
//
|
|
// Return Value:
|
|
// SUCCESS: If all the values are initiaized successfully
|
|
// Appropriate error code otherwise
|
|
{
|
|
|
|
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
NDIS_HANDLE PacketPoolHandle = NULL;
|
|
PSLIST_HEADER pSlistHead = NULL;
|
|
extern UINT NumRecvFifos ;
|
|
UINT AllocateNumBuffers = NumRecvFifos;
|
|
NIC_PACKET_POOL PacketPool;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==> nicInitRecvFifoDataStructures pVc %x",pRecvFIFOVc ) );
|
|
|
|
do
|
|
{
|
|
PacketPool.Handle = NULL;
|
|
|
|
//
|
|
// Initialize the PacketPool
|
|
//
|
|
|
|
NdisAllocatePacketPoolEx ( &NdisStatus,
|
|
&PacketPool.Handle,
|
|
MIN_PACKET_POOL_SIZE,
|
|
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
|
|
sizeof (RSVD) );
|
|
|
|
if (NdisStatus!= NDIS_STATUS_SUCCESS)
|
|
{
|
|
ASSERT(NdisStatus != NDIS_STATUS_SUCCESS);
|
|
pRecvFIFOVc->PacketPool.Handle = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Do not acquire the lock as we cannot have two make
|
|
// calls for the same Vc at the same time
|
|
//
|
|
|
|
//
|
|
// Create an S-list and intialize its structures
|
|
//
|
|
|
|
ExInitializeSListHead (&pRecvFIFOVc->FifoSListHead);
|
|
|
|
KeInitializeSpinLock (&pRecvFIFOVc->FifoSListSpinLock);
|
|
|
|
pRecvFIFOVc->Hdr.MTU = pRecvFIFOVc->Hdr.Nic1394MediaParams.MTU ;
|
|
|
|
TRACE( TL_I, TM_Cm, ( " Recv FIFO MTU is %d ", pRecvFIFOVc->Hdr.MTU ) );
|
|
|
|
|
|
ASSERT (pRecvFIFOVc->Hdr.MTU >= 512);
|
|
|
|
|
|
|
|
//
|
|
// Now, fill the Slist with buffers.
|
|
//
|
|
|
|
NdisStatus = nicFillAllocateAddressRangeSList (pRecvFIFOVc, &AllocateNumBuffers);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// nicFillAllocateAddressRangeSlist does its own clean up
|
|
// but we should free the Packet Pool Allocated above
|
|
//
|
|
if (PacketPool.Handle != NULL)
|
|
{
|
|
nicFreePacketPool (&PacketPool);
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
ASSERT(AllocateNumBuffers == NumRecvFifos );
|
|
|
|
pRecvFIFOVc->PacketPool= PacketPool;
|
|
pRecvFIFOVc->PacketPool.AllocatedPackets = 0;
|
|
pRecvFIFOVc->NumAllocatedFifos = AllocateNumBuffers ;
|
|
|
|
|
|
TRACE( TL_V, TM_Cm, ( "PacketPool allocated at %x", PacketPool.Handle) );
|
|
|
|
} while (FALSE);
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<== nicInitRecvFifoDataStructures Status %x", NdisStatus ) );
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicUnInitRecvFifoDataStructures (
|
|
IN PRECVFIFO_VCCB pRecvFIFOVc
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Frees all the resources that were allocated in nicInitRecvFifoDataStructures
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
if (pRecvFIFOVc->PacketPool.Handle != NULL)
|
|
{
|
|
ASSERT (pRecvFIFOVc->PacketPool.AllocatedPackets == 0);
|
|
nicFreePacketPool (&pRecvFIFOVc->PacketPool);
|
|
}
|
|
|
|
pRecvFIFOVc->PacketPool.Handle = NULL;
|
|
|
|
|
|
if (pRecvFIFOVc->FifoSListHead.Alignment != 0)
|
|
{
|
|
|
|
nicFreeAllocateAddressRangeSList(pRecvFIFOVc);
|
|
|
|
ASSERT (pRecvFIFOVc->FifoSListHead.Alignment == 0)
|
|
|
|
}
|
|
|
|
pRecvFIFOVc->FifoSListHead.Alignment = 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG
|
|
nicGetMaxPayLoadForSpeed(
|
|
IN ULONG Speed,
|
|
IN ULONG mtu
|
|
)
|
|
// Function Description:
|
|
// The purpose is to map a speed to the max payload that
|
|
// can be delivered at that speed . this is limited by the Bytes PerFrameAvailable
|
|
//
|
|
// Arguments
|
|
// Speed - the speed supported by the Bus driver or the Max speed between devices
|
|
// BytesPerFrameAvailable Bytes per frame available on the bus.
|
|
//
|
|
//
|
|
// Return Value:
|
|
// Minimin of the Size determined by the payload and the size determined by the
|
|
// byte per frame available.
|
|
{
|
|
|
|
|
|
ULONG maxIsochPayload = ISOCH_PAYLOAD_400_RATE;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicGetMaxPayLoadForSpeed %x", Speed ) );
|
|
|
|
switch (Speed)
|
|
{
|
|
|
|
case SPEED_FLAGS_100:
|
|
|
|
maxIsochPayload = ISOCH_PAYLOAD_100_RATE;
|
|
break;
|
|
|
|
case SPEED_FLAGS_200:
|
|
|
|
maxIsochPayload = ISOCH_PAYLOAD_200_RATE;
|
|
break;
|
|
|
|
case SPEED_FLAGS_400:
|
|
|
|
maxIsochPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
|
|
case SPEED_FLAGS_800:
|
|
|
|
maxIsochPayload = ISOCH_PAYLOAD_800_RATE;
|
|
break;
|
|
|
|
case SPEED_FLAGS_1600:
|
|
|
|
maxIsochPayload = ISOCH_PAYLOAD_1600_RATE;
|
|
break;
|
|
|
|
default :
|
|
|
|
TRACE( TL_A, TM_Cm, ( "Invalid Speed %x", Speed ) );
|
|
ASSERT (Speed < SPEED_FLAGS_1600);
|
|
maxIsochPayload = ISOCH_PAYLOAD_1600_RATE;
|
|
break;
|
|
|
|
}
|
|
|
|
if (maxIsochPayload > mtu)
|
|
{
|
|
maxIsochPayload = mtu;
|
|
}
|
|
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<==nicGetMaxPayLoadForSpeed, payload %x", maxIsochPayload ) );
|
|
|
|
return maxIsochPayload;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------
|
|
// SAP function - all of them return failure
|
|
//-------------------------------------------------------------------------------
|
|
|
|
NDIS_STATUS
|
|
nicRegisterSapHandler(
|
|
IN NDIS_HANDLE CallMgrAfContext,
|
|
IN PCO_SAP Sap,
|
|
IN NDIS_HANDLE NdisSapHandle,
|
|
OUT PNDIS_HANDLE CallMgrSapContext
|
|
)
|
|
{
|
|
|
|
*CallMgrSapContext = NULL;
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicDeregisterSapHandler(
|
|
IN NDIS_HANDLE CallMgrSapContext
|
|
)
|
|
{
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
nicCmDropPartyHandler(
|
|
IN NDIS_HANDLE CallMgrPartyContext,
|
|
IN PVOID CloseData OPTIONAL,
|
|
IN UINT Size OPTIONAL
|
|
)
|
|
{
|
|
return NDIS_STATUS_FAILURE;
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
nicCmAddPartyHandler(
|
|
IN NDIS_HANDLE CallMgrVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters,
|
|
IN NDIS_HANDLE NdisPartyHandle,
|
|
OUT PNDIS_HANDLE CallMgrPartyContext
|
|
)
|
|
{
|
|
*CallMgrPartyContext = NULL;
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicAllocateChannelResourcesAndListen (
|
|
IN PADAPTERCB pAdapter,
|
|
IN PCHANNEL_VCCB pChannelVc
|
|
)
|
|
// Function Description:
|
|
// This function isolated the reource and channel allocation portion
|
|
// of initializing a MakeCall. This lets us do the same work when the
|
|
// AddRemoteNode code path is hit and there is an existing Channel Vc
|
|
//
|
|
// Arguments
|
|
// pChannelVc, This is the send fifo that needs to be initilaized
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Success if the irps sent to the driver succeed
|
|
//
|
|
//
|
|
|
|
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
PDEVICE_OBJECT ArrayRemotePDO[NIC1394_MAX_NUMBER_NODES];
|
|
ULONG Channel = INVALID_CHANNEL;
|
|
ULONG Speed;
|
|
PNIC1394_MEDIA_PARAMETERS pN1394Params;
|
|
ULONG NumDescriptors = MAX_NUM_ISOCH_DESCRIPTOR;
|
|
PISOCH_DESCRIPTOR pIsochDescriptor = NULL;
|
|
ULONG MaxBufferSize;
|
|
ULONG MaxBytesPerFrame;
|
|
HANDLE hResource;
|
|
CYCLE_TIME CycleTime;
|
|
ULARGE_INTEGER uliChannelMap;
|
|
ULONG ResourceFlags = 0;
|
|
ULONG State = 0;
|
|
BOOLEAN fBroadcastVc = FALSE;
|
|
BOOLEAN fChannelAllocate = FALSE;
|
|
BOOLEAN fIsMultiChannel = FALSE;
|
|
enum
|
|
{
|
|
StartState,
|
|
AllocatedResources,
|
|
AllocatedBuffers,
|
|
AttachedBuffers,
|
|
IsochListen
|
|
};
|
|
|
|
|
|
STORE_CURRENT_IRQL;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==> nicAllocateChannelResourcesAndListen pAdapter %x, pChannelVc %x ",
|
|
pAdapter,pChannelVc ) );
|
|
|
|
|
|
State = StartState;
|
|
|
|
pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pChannelVc->Hdr.Nic1394MediaParams;
|
|
|
|
//
|
|
// Use the original request to figure out which channel needs to be allocated
|
|
//
|
|
fIsMultiChannel = (pN1394Params->Destination.AddressType == NIC1394AddressType_MultiChannel);
|
|
|
|
if (fIsMultiChannel == FALSE)
|
|
{
|
|
Channel = pN1394Params->Destination.Channel;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (pAdapter == NULL)
|
|
{
|
|
BREAK (TM_Cm, ("nicAllocateChannelResourcesAndListen : pAdapter == NULL ") );
|
|
}
|
|
|
|
//
|
|
// Get the max payload that is possible for isoch receives
|
|
//
|
|
|
|
if (pAdapter->Speed == 0)
|
|
{
|
|
nicUpdateLocalHostSpeed (pAdapter);
|
|
}
|
|
|
|
Speed = pAdapter->Speed;
|
|
|
|
switch (Speed)
|
|
{
|
|
case SPEED_FLAGS_100 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_100_RATE;
|
|
break;
|
|
}
|
|
case SPEED_FLAGS_200 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_200_RATE ;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_400 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_800 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_1600 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_3200 :
|
|
{
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
ASSERT (Speed <= SPEED_FLAGS_3200 && Speed != 0 );
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If the make call wants the channel to allocate we try and allocate the channel,
|
|
// In the Multichannel case, we do not allocate the channel (as this is
|
|
// for listening purposes only )
|
|
//
|
|
|
|
fBroadcastVc = (Channel == NIC1394_BROADCAST_CHANNEL);
|
|
fChannelAllocate = VC_TEST_FLAG (pChannelVc,VCBF_NeedsToAllocateChannel);
|
|
|
|
|
|
if (fChannelAllocate || fBroadcastVc )
|
|
{
|
|
ASSERT (pChannelVc->Hdr.VcType != NIC1394_MultiChannel);
|
|
|
|
NdisStatus = nicAllocateRequestedChannelMakeCallComplete( pAdapter,
|
|
pChannelVc,
|
|
&Channel );
|
|
|
|
|
|
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK( TM_Cm, ( " nicAllocateChannelResourcesAndListen : nicAllocateRequestedChannelMakeCallComplete FAILED") );
|
|
|
|
}
|
|
|
|
|
|
TRACE( TL_I, TM_Cm, ( "Using Channel %x, on remote node ", Channel ) );
|
|
|
|
ASSERT (Channel < NIC1394_MAX_NUMBER_NODES);
|
|
|
|
ResourceFlags = 0;
|
|
|
|
uliChannelMap.QuadPart = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Multichannels - no allocation just update the ullChannelMap
|
|
//
|
|
uliChannelMap = pChannelVc->uliChannelMap;
|
|
|
|
if (fIsMultiChannel == TRUE)
|
|
{
|
|
ResourceFlags = RESOURCE_USE_MULTICHANNEL;
|
|
}
|
|
else
|
|
{
|
|
pChannelVc->Channel = Channel ;
|
|
}
|
|
}
|
|
|
|
MaxBufferSize = min(pN1394Params->MTU + sizeof(GASP_HEADER) , pChannelVc->Hdr.MaxPayload);
|
|
|
|
MaxBytesPerFrame = MaxBufferSize;
|
|
|
|
TRACE( TL_V, TM_Cm, ( " MAxBufferSize %x, MaxBytesPerFrame %x", MaxBufferSize, MaxBytesPerFrame ) );
|
|
|
|
//
|
|
// Add the flags used for resources allocation
|
|
//
|
|
ResourceFlags |= (RESOURCE_USED_IN_LISTENING | RESOURCE_USE_PACKET_BASED | RESOURCE_BUFFERS_CIRCULAR);
|
|
|
|
|
|
//
|
|
// MaxBufferSize should be an integral mutiple of MaxBytesPerFram
|
|
//
|
|
ASSERT (MaxBufferSize % MaxBytesPerFrame == 0);
|
|
|
|
//
|
|
// Noe allocate the resource
|
|
//
|
|
NdisStatus = nicIsochAllocateResources( pAdapter,
|
|
Speed,
|
|
ResourceFlags,
|
|
Channel,
|
|
MaxBytesPerFrame,
|
|
NumDescriptors,
|
|
MaxBufferSize,
|
|
0, //QuadletsToStrip,
|
|
uliChannelMap,
|
|
&hResource);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
hResource = NULL;
|
|
BREAK(TM_Cm, ( "Allocate Resources Failed. Make Call failed ") );
|
|
}
|
|
|
|
State = AllocatedResources;
|
|
|
|
ASSERT (NumDescriptors != 0);
|
|
|
|
ASSERT (pChannelVc->Hdr.MTU != 0);
|
|
|
|
//
|
|
// Get Isoch Descriptors that will be submitted to the Bus drivers
|
|
//
|
|
|
|
//
|
|
// Add room for the Isoch Header and Isoch prefix
|
|
//
|
|
MaxBufferSize += ISOCH_PREFIX_LENGTH ;
|
|
|
|
NdisStatus = nicAllocateAndInitializeIsochDescriptors (pChannelVc,
|
|
NumDescriptors,
|
|
MaxBufferSize,
|
|
&pIsochDescriptor );
|
|
if(NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
|
|
BREAK (TM_Cm, (" nicAllocateAndInitializeIsochDescriptors failed, Make Call Failed") );
|
|
}
|
|
|
|
ASSERT (pIsochDescriptor != NULL);
|
|
|
|
State = AllocatedBuffers;
|
|
|
|
NdisStatus = nicIsochAttachBuffers( pAdapter,
|
|
hResource,
|
|
NumDescriptors,
|
|
pIsochDescriptor);
|
|
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK (TM_Cm, "nicIsochAttachBuffers FAILED");
|
|
}
|
|
|
|
State = AttachedBuffers;
|
|
|
|
//
|
|
// Start the Listen
|
|
//
|
|
NdisZeroMemory (&CycleTime, sizeof(CycleTime));
|
|
|
|
NdisStatus = nicIsochListen (pAdapter,
|
|
hResource,
|
|
0,
|
|
CycleTime ); // Cycle Time is Zero
|
|
//
|
|
// Update the Vc structure, because we have now succeeded
|
|
//
|
|
State = IsochListen;
|
|
|
|
VC_ACQUIRE_LOCK (pChannelVc);
|
|
|
|
//
|
|
// If broadcast channel, then decrease the speed setting, and fragment
|
|
//
|
|
if (Channel == NIC1394_BROADCAST_CHANNEL)
|
|
{
|
|
|
|
Speed = SPEED_FLAGS_200 ;
|
|
pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_200_RATE ;
|
|
}
|
|
|
|
|
|
|
|
pChannelVc->Channel = Channel;
|
|
pChannelVc->MaxBufferSize = MaxBufferSize - ISOCH_PREFIX_LENGTH;
|
|
pChannelVc->Speed = Speed;
|
|
|
|
pChannelVc->hResource = hResource;
|
|
//
|
|
// Reference Call for allocated resource handle
|
|
//
|
|
nicReferenceCall ( (PVCCB) pChannelVc, "nicAllocateRequestedChannelMakeCallComplete - allocate resources ");
|
|
|
|
pChannelVc->NumDescriptors = NumDescriptors;
|
|
pChannelVc->pIsochDescriptor = pIsochDescriptor;
|
|
//
|
|
// Reference the call because we will now need to detach buffers
|
|
//
|
|
nicReferenceCall ( (PVCCB) pChannelVc, "nicAllocateRequestedChannelMakeCallComplete - Attach Buffers");
|
|
|
|
|
|
//
|
|
// We have succeded in allocating all resources.
|
|
// If the Freed Resources flag is set it needs to be cleared
|
|
//
|
|
VC_CLEAR_FLAGS (pChannelVc, VCBF_FreedResources);
|
|
VC_RELEASE_LOCK (pChannelVc);
|
|
|
|
//
|
|
// No more failures
|
|
//
|
|
} while (FALSE);
|
|
|
|
|
|
//
|
|
// Time to do clean up based on what resources were allocated.
|
|
// There are no failures after the point where the refs for
|
|
// Allocate Resources and Attach Buffers are added, so
|
|
// No Derefs in the following code except in ( FreeIsochDesc)
|
|
//
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS )
|
|
{
|
|
BOOLEAN fAllocatedChannel = FALSE;
|
|
|
|
switch (State)
|
|
{
|
|
case IsochListen:
|
|
{
|
|
nicIsochStop(pAdapter, hResource);
|
|
FALL_THROUGH
|
|
}
|
|
case AttachedBuffers:
|
|
{
|
|
nicIsochDetachBuffers( pAdapter,
|
|
hResource,
|
|
NumDescriptors,
|
|
pIsochDescriptor );
|
|
|
|
|
|
FALL_THROUGH;
|
|
}
|
|
case AllocatedBuffers:
|
|
{
|
|
//
|
|
// Free the isoch Buffers and Descriptors that were
|
|
// allocated
|
|
//
|
|
nicFreeIsochDescriptors(NumDescriptors,
|
|
pIsochDescriptor,
|
|
(PVCCB) pChannelVc);
|
|
|
|
FALL_THROUGH
|
|
}
|
|
|
|
case AllocatedResources:
|
|
{
|
|
//
|
|
// Free the Isoch Resources Handle
|
|
//
|
|
nicIsochFreeResources (pAdapter, hResource);
|
|
FALL_THROUGH
|
|
}
|
|
|
|
case StartState:
|
|
{
|
|
FALL_THROUGH
|
|
}
|
|
default:
|
|
{
|
|
|
|
break;
|
|
}
|
|
}
|
|
VC_ACQUIRE_LOCK (pChannelVc);
|
|
|
|
//
|
|
// Update Flags in the VC structure
|
|
//
|
|
VC_SET_FLAG (pChannelVc, VCBF_FreedResources);
|
|
|
|
fAllocatedChannel = VC_TEST_FLAGS( pChannelVc, VCBF_AllocatedChannel);
|
|
|
|
//
|
|
// Do we need to free a channel as well
|
|
//
|
|
if (fAllocatedChannel == TRUE)
|
|
{
|
|
Channel = pChannelVc->Channel;
|
|
pChannelVc->Channel = INVALID_CHANNEL;
|
|
|
|
nicDereferenceCall ((PVCCB) pChannelVc, "Free Allocated Channel");
|
|
}
|
|
VC_RELEASE_LOCK (pChannelVc);
|
|
|
|
|
|
if (fAllocatedChannel)
|
|
{
|
|
nicFreeChannel (pAdapter, pChannelVc->Channel);
|
|
}
|
|
|
|
|
|
} // end of failure code path
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<== nicAllocateChannelResourcesAndListen NdisStatus %x ",NdisStatus) );
|
|
|
|
MATCH_IRQL;
|
|
return NdisStatus;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
nicQueryRemoteNodeCaps (
|
|
IN PADAPTERCB pAdapter,
|
|
IN PREMOTE_NODE pRemoteNode,
|
|
OUT PULONG pSpeedTo,
|
|
OUT PULONG pMaxBufferSize,
|
|
OUT PULONG pMaxRec
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Queries the remote Node for speed and max size
|
|
|
|
Arguments:
|
|
pSpeedTo -- max speed to the remote node. From nodes config rom.
|
|
in units of SCODE_XXX_RATE.
|
|
pMaxBufferSize -- max buffer size to use ( this is the min of local,
|
|
remote and max allowed by *pSpeedTo).
|
|
pMaxRec -- maxrec of the remote node -- from the node's config
|
|
rom.
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
|
|
ULONG Speed = 0; // Speed in units of SPEED_FLAG_XXX
|
|
ULONG MaxBufferSize;
|
|
PVOID pCRom = NULL;
|
|
PCONFIG_ROM pBusInfo = NULL;
|
|
ULONG SpeedMaxRec = 0;
|
|
ULONG MaxRec= 0;
|
|
ULONG MinMaxRec= 0;
|
|
|
|
TRACE( TL_T, TM_Cm, ( "==> nicQueryRemoteNodeCaps pRemoteNode%x ",pRemoteNode) );
|
|
|
|
do
|
|
{
|
|
ASSERT (KeGetCurrentIrql()==PASSIVE_LEVEL);
|
|
|
|
ADAPTER_ACQUIRE_LOCK (pAdapter);
|
|
|
|
if (REMOTE_NODE_ACTIVE (pRemoteNode) == FALSE)
|
|
{
|
|
NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
break;
|
|
}
|
|
|
|
ADAPTER_RELEASE_LOCK (pAdapter);
|
|
|
|
|
|
NdisStatus = nicGetMaxSpeedBetweenDevices (pAdapter,
|
|
1 ,
|
|
&pRemoteNode->pPdo,
|
|
&Speed);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK (TM_Cm, (" nicQueryRemoteNodeCaps : nicGetMaxSpeedBetweenDevices FAILED") );
|
|
|
|
}
|
|
|
|
TRACE( TL_V, TM_Cm, ( "nicGetMaxSpeedBetweenDevices Speed %x ",Speed) );
|
|
|
|
//
|
|
// This is the MaxRec from the Actual speed of
|
|
// the link.
|
|
//
|
|
|
|
SpeedMaxRec = nicGetMaxRecFromSpeed(Speed);
|
|
|
|
|
|
|
|
//
|
|
// Now get the max rec from the config rom
|
|
//
|
|
|
|
NdisStatus = nicGetConfigRom (pRemoteNode->pPdo, &pCRom);
|
|
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
BREAK (TM_Cm, (" nicQueryRemoteNodeCaps : nicGetMaxSpeedBetweenDevices FAILED") );
|
|
|
|
}
|
|
|
|
//
|
|
// Now extract the bus info, and get the remoteNode's MaxRec
|
|
// The max rec is a 4-bit field at location 0x0000f000.
|
|
// See for example Figure 11-3: Format of the Bus_Info_Block in
|
|
// the Mind Share Inc's FireWire System Architecture book.
|
|
//
|
|
//
|
|
pBusInfo = (PCONFIG_ROM) pCRom;
|
|
|
|
MaxRec = SWAPBYTES_ULONG (pBusInfo->CR_BusInfoBlockCaps);
|
|
|
|
MaxRec &= 0xf000;
|
|
|
|
MaxRec = MaxRec >> 12;
|
|
|
|
|
|
//
|
|
// Take the minimum of the adapter, the remote node
|
|
// and the link's maxRec
|
|
//
|
|
MinMaxRec = min (MaxRec, pAdapter->MaxRec);
|
|
MinMaxRec = min (MinMaxRec, SpeedMaxRec);
|
|
|
|
switch (MinMaxRec)
|
|
{
|
|
case MAX_REC_100_RATE:
|
|
{
|
|
MaxBufferSize = ASYNC_PAYLOAD_100_RATE ;
|
|
break;
|
|
}
|
|
case MAX_REC_200_RATE:
|
|
{
|
|
MaxBufferSize = ASYNC_PAYLOAD_200_RATE;
|
|
break;
|
|
}
|
|
case MAX_REC_400_RATE :
|
|
{
|
|
MaxBufferSize = ASYNC_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
//
|
|
// Use the 400 size for all larger payloads.
|
|
//
|
|
MaxBufferSize = ASYNC_PAYLOAD_400_RATE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
TRACE( TL_N, TM_Cm, (" MaxRec %x\n", MaxRec ) );
|
|
|
|
} while (FALSE);
|
|
|
|
if (NdisStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Speed = nicSpeedFlagsToSCode(Speed);
|
|
*pSpeedTo = Speed;
|
|
*pMaxBufferSize = MaxBufferSize;
|
|
*pMaxRec = MaxRec;
|
|
|
|
// Update the remote node's cached caps.
|
|
//
|
|
REMOTE_NODE_ACQUIRE_LOCK (pRemoteNode);
|
|
pRemoteNode->CachedCaps.SpeedTo = Speed;
|
|
pRemoteNode->CachedCaps.EffectiveMaxBufferSize = MaxBufferSize;
|
|
pRemoteNode->CachedCaps.MaxRec = MaxRec;
|
|
|
|
REMOTE_NODE_RELEASE_LOCK (pRemoteNode);
|
|
}
|
|
|
|
if (pCRom != NULL)
|
|
{
|
|
FREE_NONPAGED (pCRom);
|
|
}
|
|
|
|
TRACE( TL_T, TM_Cm, ( "<== nicQueryRemoteNodeCaps pRemoteNode%x , NdisStatus %x",pRemoteNode, NdisStatus) );
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
nicInterceptMakeCallParameters (
|
|
PCO_MEDIA_PARAMETERS pMedia
|
|
)
|
|
|
|
{
|
|
|
|
PNIC1394_MEDIA_PARAMETERS p1394Params = (PNIC1394_MEDIA_PARAMETERS )(pMedia->MediaSpecific.Parameters);
|
|
|
|
#if INTERCEPT_MAKE_CALL
|
|
|
|
|
|
if (p1394Params->Destination.AddressType == NIC1394AddressType_MultiChannel)
|
|
{
|
|
p1394Params->Destination.AddressType = NIC1394AddressType_Channel;
|
|
p1394Params->Destination.Channel = 0x3a;
|
|
p1394Params->Flags |= NIC1394_VCFLAG_ALLOCATE;
|
|
pMedia->Flags |= TRANSMIT_VC;
|
|
pMedia->Flags &= (~RECEIVE_VC);
|
|
return;
|
|
|
|
}
|
|
|
|
if (p1394Params->Destination.AddressType == NIC1394AddressType_Ethernet)
|
|
{
|
|
p1394Params->Destination.AddressType = NIC1394AddressType_Channel;
|
|
p1394Params->Destination.Channel = 0x3a;
|
|
pMedia->Flags |= RECEIVE_VC;
|
|
pMedia->Flags &= (~TRANSMIT_VC);
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
UINT
|
|
nicSpeedFlagsToSCode(
|
|
IN UINT SpeedFlags
|
|
)
|
|
{
|
|
UINT SCode = SCODE_400_RATE;
|
|
|
|
switch (SpeedFlags)
|
|
{
|
|
case SPEED_FLAGS_100 :
|
|
{
|
|
SCode = SCODE_100_RATE;
|
|
break;
|
|
}
|
|
case SPEED_FLAGS_200 :
|
|
{
|
|
SCode = SCODE_200_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_400 :
|
|
{
|
|
SCode = SCODE_400_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_800 :
|
|
{
|
|
SCode = SCODE_800_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_1600 :
|
|
{
|
|
SCode = SCODE_1600_RATE;
|
|
break;
|
|
}
|
|
|
|
case SPEED_FLAGS_3200 :
|
|
{
|
|
SCode = SCODE_3200_RATE;
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
ASSERT (!"SpeedFlags out of range");
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return SCode;
|
|
}
|
|
|