Leaked source code of windows server 2003
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

  1. //
  2. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  3. //
  4. // cm.c
  5. //
  6. // IEEE1394 mini-port/call-manager driver
  7. //
  8. // Call Manager routines
  9. //
  10. // 12/28/1998 JosephJ Created
  11. // 01/01/1999 ADube modified - Added Remote Node Capability
  12. //
  13. #include "precomp.h"
  14. //-----------------------------------------------------------------------------
  15. // Call-manager handlers and completers
  16. //-----------------------------------------------------------------------------
  17. NDIS_STATUS
  18. NicCmOpenAf(
  19. IN NDIS_HANDLE CallMgrBindingContext,
  20. IN PCO_ADDRESS_FAMILY AddressFamily,
  21. IN NDIS_HANDLE NdisAfHandle,
  22. OUT PNDIS_HANDLE CallMgrAfContext )
  23. // Standard 'CmCmOpenAfHandler' routine called by NDIS when a client
  24. // requests to open an address family. See DDK doc.
  25. //
  26. {
  27. ADAPTERCB* pAdapter;
  28. NDIS_HANDLE hExistingAf;
  29. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  30. TIMESTAMP_ENTRY ("==>Open Af");
  31. TRACE( TL_T, TM_Cm, ( "==>NicCmOpenAf" ) );
  32. pAdapter = (ADAPTERCB* )CallMgrBindingContext;
  33. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  34. {
  35. ASSERT( !"Atag?" );
  36. return NDIS_STATUS_INVALID_DATA;
  37. }
  38. if (AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_1394
  39. || AddressFamily->MajorVersion != NDIS_MajorVersion
  40. || AddressFamily->MinorVersion != NDIS_MinorVersion)
  41. {
  42. return NDIS_STATUS_BAD_VERSION;
  43. }
  44. do
  45. {
  46. AFCB *pAF = NULL;
  47. // Allocate and initialize the adress family structure.
  48. //
  49. pAF = ALLOC_NONPAGED( sizeof(*pAF), MTAG_AFCB );
  50. if (!pAF)
  51. {
  52. Status = NDIS_STATUS_RESOURCES;
  53. break;
  54. }
  55. NdisZeroMemory( pAF, sizeof(*pAF) );
  56. // Set a marker for easier memory dump browsing and future assertions.
  57. //
  58. pAF->ulTag = MTAG_AFCB;
  59. // Save the NDIS handle associated with this AF for use in future
  60. // NdisXxx calls.
  61. //
  62. ADAPTER_ACQUIRE_LOCK( pAdapter );
  63. pAF->NdisAfHandle = NdisAfHandle;
  64. // Initialize the VC list for this AF.
  65. //
  66. InitializeListHead( &pAF->AFVCList );
  67. // Set up linkages and references.
  68. //
  69. pAF->pAdapter = pAdapter;
  70. nicReferenceAF( pAF ); // OpenAF
  71. nicReferenceAdapter( pAdapter ,"NicCmOpenAf "); // OpenAF
  72. InsertHeadList(&pAdapter->AFList, &pAF->linkAFCB);
  73. // Return pAF as the address family context.
  74. //
  75. *CallMgrAfContext = (PNDIS_HANDLE )pAF;
  76. ADAPTER_RELEASE_LOCK (pAdapter);
  77. } while (FALSE);
  78. TRACE( TL_T, TM_Cm, ( "NicCmOpenAf Status %x", Status ) );
  79. TIMESTAMP_EXIT("<==Open Af ");
  80. return Status;
  81. }
  82. NDIS_STATUS
  83. NicCmCloseAf(
  84. IN NDIS_HANDLE CallMgrAfContext )
  85. // Standard 'CmCloseAfHandler' routine called by NDIS when a client
  86. // requests to close an address family. See DDK doc.
  87. //
  88. {
  89. AFCB* pAF;
  90. TIMESTAMP_ENTRY ("==>CloseAf");
  91. TRACE( TL_T, TM_Cm, ( "NicCmCloseAf" ) );
  92. pAF = (AFCB* )CallMgrAfContext;
  93. if (pAF->ulTag != MTAG_AFCB)
  94. {
  95. ASSERT( !"AFCB?" );
  96. return NDIS_STATUS_INVALID_DATA;
  97. }
  98. nicSetFlags (&pAF->ulFlags, ACBF_ClosePending);
  99. // This dereference will eventually lead to us calling
  100. // NdisMCmCloseAfComplete.
  101. //
  102. //
  103. // The references that were made in OpenAf
  104. //
  105. nicDereferenceAF( pAF );
  106. TRACE( TL_T, TM_Cm, ( "NicCmCloseAf pending" ) );
  107. TIMESTAMP_EXIT ("<==Close Af");
  108. return NDIS_STATUS_PENDING;
  109. }
  110. NDIS_STATUS
  111. NicCmCreateVc(
  112. IN NDIS_HANDLE ProtocolAfContext,
  113. IN NDIS_HANDLE NdisVcHandle,
  114. OUT PNDIS_HANDLE ProtocolVcContext )
  115. // Standard 'CmCreateVc' routine called by NDIS in response to a
  116. // client's request to create a virtual circuit. This
  117. // call must return synchronously.
  118. //
  119. {
  120. NDIS_STATUS status;
  121. AFCB* pAF;
  122. VCCB* pVc;
  123. TRACE( TL_T, TM_Cm, ( "==>NicCmCreateVc, Af %x",ProtocolAfContext) );
  124. pAF = (AFCB* )ProtocolAfContext;
  125. if (pAF->ulTag != MTAG_AFCB)
  126. {
  127. ASSERT( !"Atag?" );
  128. return NDIS_STATUS_INVALID_DATA;
  129. }
  130. // Allocate and zero a VC control block, then make any non-zero
  131. // initializations.
  132. //
  133. pVc = ALLOC_VCCB( pAdapter );
  134. if (!pVc)
  135. {
  136. ASSERT( !"Alloc VC?" );
  137. return NDIS_STATUS_RESOURCES;
  138. }
  139. NdisZeroMemory( pVc, sizeof(*pVc) );
  140. TRACE( TL_I, TM_Cm, ( "NicCmCreateVc $%p", pVc ) );
  141. // Set a marker for easier memory dump browsing.
  142. //
  143. pVc->Hdr.ulTag = MTAG_VCCB;
  144. // Save the NDIS handle of this VC for use in indications to NDIS later.
  145. //
  146. pVc->Hdr.NdisVcHandle = NdisVcHandle;
  147. // The VC control block's address is the VC context we return to NDIS.
  148. //
  149. *ProtocolVcContext = (NDIS_HANDLE )pVc;
  150. // Add a reference to the control block and the associated address family
  151. // that is removed by LmpCoDeleteVc. Add the linkages.
  152. //
  153. pVc->Hdr.pAF = pAF;
  154. // Initialize the VC's copy of the spinlock to point to the Adapter's spinlock.
  155. //
  156. pVc->Hdr.plock = &pAF->pAdapter->lock;
  157. nicReferenceVc( pVc ); // Create VC
  158. nicReferenceAF( pAF ); // Create VC
  159. VC_SET_FLAG (pVc, VCBF_VcCreated);
  160. // Add to list of VC's associated with this AF
  161. //
  162. AF_ACQUIRE_LOCK (pAF);
  163. InsertHeadList(&pAF->AFVCList, &pVc->Hdr.linkAFVcs);
  164. AF_RELEASE_LOCK (pAF);
  165. TRACE( TL_T, TM_Cm, ( "<==NicCmCreateVc=0" ) );
  166. return NDIS_STATUS_SUCCESS;
  167. }
  168. NDIS_STATUS
  169. NicCmDeleteVc(
  170. IN NDIS_HANDLE ProtocolVcContext )
  171. // Standard 'CmDeleteVc' routine called by NDIS in response to a
  172. // client's request to delete a virtual circuit. This
  173. // call must return synchronously.
  174. //
  175. {
  176. VCCB* pVc = NULL;
  177. AFCB *pAF = NULL;
  178. PADAPTERCB pAdapter = NULL;
  179. TRACE( TL_T, TM_Cm, ( "==>NicCmDelVc($%p)", ProtocolVcContext ) );
  180. pVc = (VCCB* )ProtocolVcContext;
  181. if (pVc->Hdr.ulTag != MTAG_VCCB)
  182. {
  183. ASSERT( !"Vtag?" );
  184. return NDIS_STATUS_INVALID_DATA;
  185. }
  186. VC_ACQUIRE_LOCK (pVc);
  187. // Set vc flag to deleted, and remove back pointer to AF
  188. //
  189. {
  190. // This flag catches attempts by the client to delete the VC twice.
  191. //
  192. if (nicReadFlags( &pVc->Hdr.ulFlags ) & VCBF_VcDeleted)
  193. {
  194. TRACE( TL_A, TM_Cm, ( "VC $%p re-deleted?", pVc ) );
  195. VC_RELEASE_LOCK ( pVc );
  196. ASSERT (0);
  197. return NDIS_STATUS_FAILURE;
  198. }
  199. nicSetFlags( &pVc->Hdr.ulFlags, VCBF_VcDeleted );
  200. pAF = pVc->Hdr.pAF;
  201. }
  202. // Unlink from the AF vc list.
  203. //
  204. {
  205. nicRemoveEntryList (&pVc->Hdr.linkAFVcs);
  206. InitializeListHead (&pVc->Hdr.linkAFVcs);
  207. pVc->Hdr.pAF = NULL;
  208. }
  209. // Remove the references added by NicCmCreateVc.
  210. //
  211. VC_RELEASE_LOCK (pVc);
  212. nicDereferenceAF( pAF );
  213. //
  214. // This deref could cause the Vc to be deleted. Don't touch the Vc after that
  215. //
  216. nicDereferenceVc( pVc );
  217. TRACE( TL_T, TM_Cm, ( "<==NicCmDelVc 0" ) );
  218. return NDIS_STATUS_SUCCESS;
  219. }
  220. NDIS_STATUS
  221. NicCmMakeCall(
  222. IN NDIS_HANDLE CallMgrVcContext,
  223. IN OUT PCO_CALL_PARAMETERS pCallParameters,
  224. IN NDIS_HANDLE NdisPartyHandle,
  225. OUT PNDIS_HANDLE CallMgrPartyContext )
  226. // Function Description:
  227. //
  228. // Standard 'CmMakeCallHandler' routine called by NDIS when the a client
  229. // has requested to connect to a remote end-point. See DDK doc.
  230. //
  231. // Arguments
  232. // Call Mge context:
  233. // Call Parameters
  234. // Optiuonal NdisPartyHandle
  235. // Return Value:
  236. //
  237. //
  238. {
  239. PVCCB pVc = (VCCB* )CallMgrVcContext;
  240. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  241. PADAPTERCB pAdapter = NULL;
  242. NDIS_WORK_ITEM* pMakeCallCompleteWorkItem = NULL;
  243. PCO_MEDIA_PARAMETERS pMediaParams = pCallParameters->MediaParameters;
  244. PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
  245. TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCall" ) );
  246. nicInterceptMakeCallParameters(pMediaParams);
  247. do
  248. {
  249. if (NdisPartyHandle != NULL ||
  250. pVc == NULL ||
  251. pCallParameters == NULL ||
  252. pCallParameters->MediaParameters == NULL ||
  253. pCallParameters->MediaParameters->MediaSpecific.ParamType != NIC1394_MEDIA_SPECIFIC ||
  254. pN1394Params->MTU == 0)
  255. {
  256. //
  257. // We do not support these parameters
  258. //
  259. return NDIS_STATUS_FAILURE;
  260. }
  261. pAdapter = pVc->Hdr.pAF->pAdapter;
  262. ASSERT (pAdapter != NULL);
  263. //
  264. // Reference the Vc so it does not go during this makeCall
  265. // This is decremented in the failure code path or the workitem or
  266. // when the call is closed
  267. VC_ACQUIRE_LOCK (pVc);
  268. nicReferenceVc (pVc);
  269. //
  270. // Erase all references to past calls
  271. //
  272. VC_CLEAR_FLAGS (pVc, VCBM_NoActiveCall);
  273. VC_SET_FLAG (pVc, VCBF_MakeCallPending);
  274. //
  275. // Initialize the Call's refcount to 1 beacuse we are about to begin to allocate resources to the MakeCall
  276. // This will be decremented in the closecall handler. Or in the failure code path
  277. //
  278. nicInitializeCallRef (pVc);
  279. VC_RELEASE_LOCK (pVc);
  280. pVc->Hdr.pCallParameters = pCallParameters;
  281. NdisStatus = nicCmGenericMakeCallInit (pVc);
  282. if (NdisStatus != NDIS_STATUS_SUCCESS)
  283. {
  284. TRACE( TL_A, TM_Cm, ( "nicCmGenericMakeCallInit did not succeed- Make Call FAILED($%p)", CallMgrVcContext ) );
  285. break;
  286. }
  287. //
  288. // If status is pending it means that we want to make this an asynchronous call
  289. // The completing th
  290. pMakeCallCompleteWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  291. if (pMakeCallCompleteWorkItem == NULL)
  292. {
  293. TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem - Make Call FAILED($%p)", CallMgrVcContext ) );
  294. NdisStatus = NDIS_STATUS_RESOURCES;
  295. break;
  296. }
  297. //
  298. // Now schedule the work item so it runs at passive level and pass the Vc as
  299. // an argument
  300. //
  301. NdisInitializeWorkItem ( pMakeCallCompleteWorkItem,
  302. (NDIS_PROC)nicCmMakeCallComplete,
  303. (PVOID)pVc );
  304. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  305. NdisScheduleWorkItem (pMakeCallCompleteWorkItem);
  306. NdisStatus = NDIS_STATUS_PENDING;
  307. } while (FALSE);
  308. if (!NT_SUCCESS (NdisStatus))
  309. {
  310. //
  311. // Clean up, close the ref on the Calls, Deref the Call. And Update the Vc
  312. // to show that we have failed the make call
  313. //
  314. nicCmGenrericMakeCallFailure (pVc);
  315. }
  316. TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCall, Vc %x, Status%x", pVc, NdisStatus ) );
  317. return NdisStatus;
  318. }
  319. NDIS_STATUS
  320. nicCmGenericMakeCallInitChannels (
  321. IN PCHANNEL_VCCB pChannelVc,
  322. VC_SEND_RECEIVE VcType
  323. )
  324. /*++
  325. Routine Description:
  326. Initialze handlers for Send / Recv Channels
  327. Arguments:
  328. Return Value:
  329. --*/
  330. {
  331. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; // As there are no allocations
  332. PCO_MEDIA_PARAMETERS pMediaParams = pChannelVc->Hdr.pCallParameters->MediaParameters;
  333. PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
  334. if ((pN1394Params->Flags & NIC1394_VCFLAG_ALLOCATE) == NIC1394_VCFLAG_ALLOCATE)
  335. {
  336. TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Vc %x nneds to allocate channel %x",
  337. pChannelVc,
  338. pN1394Params->Destination.Channel) );
  339. VC_SET_FLAG (pChannelVc, VCBF_NeedsToAllocateChannel);
  340. }
  341. switch (VcType)
  342. {
  343. case TransmitAndReceiveVc:
  344. {
  345. //
  346. // Channels will be defaulted to have Send And Receive Capabilities
  347. //
  348. TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Transmit and Receive Vc Vc %x", pChannelVc ) );
  349. pChannelVc->Hdr.VcType = NIC1394_SendRecvChannel;
  350. pChannelVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitSendRecvChannelVc;
  351. pChannelVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendRecvChannel;
  352. pChannelVc->Hdr.VcHandlers.SendPackets = AsyncStreamSendPacketsHandler;
  353. break;
  354. }
  355. case ReceiveVc:
  356. {
  357. TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Receive Vc %x", pChannelVc ) );
  358. pChannelVc->Hdr.VcType = NIC1394_RecvChannel;
  359. pChannelVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitSendRecvChannelVc;
  360. pChannelVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendRecvChannel;
  361. pChannelVc->Hdr.VcHandlers.SendPackets = DummySendPacketsHandler;
  362. break;
  363. }
  364. case TransmitVc:
  365. {
  366. TRACE( TL_V, TM_Cm, ( " MakeCall- Channel Transmit Vc Vc %x", pChannelVc ) );
  367. pChannelVc->Hdr.VcType = NIC1394_SendChannel;
  368. pChannelVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallSendChannel ;
  369. pChannelVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendChannel;
  370. pChannelVc->Hdr.VcHandlers.SendPackets = AsyncStreamSendPacketsHandler;
  371. break;
  372. }
  373. default:
  374. {
  375. NdisStatus = NDIS_STATUS_FAILURE;
  376. }
  377. }
  378. return NdisStatus;
  379. }
  380. NDIS_STATUS
  381. nicCmGenericMakeCallInitFifo (
  382. IN PVCCB pVc,
  383. VC_SEND_RECEIVE VcType
  384. )
  385. /*++
  386. Routine Description:
  387. Initializes Fifo Vcs'. This only fails a recv fifo is asked for and the
  388. adapter already has one.
  389. Arguments:
  390. pVc
  391. Return Value:
  392. --*/
  393. {
  394. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; //As there are no allocations
  395. PCO_MEDIA_PARAMETERS pMediaParams = pVc->Hdr.pCallParameters->MediaParameters;
  396. PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
  397. switch (VcType)
  398. {
  399. case ReceiveVc:
  400. {
  401. //
  402. // Recv FifoVcs
  403. //
  404. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  405. PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB) pVc;
  406. ASSERT(pMediaParams->Flags & RECEIVE_VC);
  407. TRACE( TL_V, TM_Cm, ( " MakeCall - AsyncReceiveVc Vc %x", pVc ) );
  408. pVc->Hdr.VcType = NIC1394_RecvFIFO;
  409. pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitRecvFIFOVc;
  410. pVc->Hdr.VcHandlers.SendPackets = DummySendPacketsHandler;
  411. pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallRecvFIFO;
  412. //
  413. // There are two reasons to fail a RecvFIFO Make call.
  414. // One, a REcvFIFO already exists and second UniqueId != 0
  415. //
  416. if (pAdapter->pRecvFIFOVc == NULL && pN1394Params->Destination.FifoAddress.UniqueID == 0 )
  417. {
  418. ADAPTER_ACQUIRE_LOCK (pAdapter);
  419. pAdapter->pRecvFIFOVc = (PRECVFIFO_VCCB)pVc;
  420. //
  421. // Since the adapter now has a pointer to the Vc, increment the Refcount.
  422. // This will be decremented in the CloseCall
  423. //
  424. nicReferenceVc (pVc);
  425. ADAPTER_RELEASE_LOCK (pAdapter);
  426. }
  427. else
  428. {
  429. TRACE( TL_A, TM_Cm, ( "Adapter at %x, already has a recvFIFO. Field is at %x", pAdapter, &pAdapter->pRecvFIFOVc ) );
  430. ASSERT (pAdapter->pRecvFIFOVc == NULL);
  431. NdisStatus = NDIS_STATUS_FAILURE;
  432. pVc->Hdr.VcHandlers.MakeCallHandler = NULL;
  433. pVc->Hdr.VcHandlers.CloseCallHandler = NULL;
  434. }
  435. break;
  436. }
  437. case TransmitVc:
  438. {
  439. //
  440. // Send Fifo Vcs
  441. //
  442. TRACE( TL_V, TM_Cm, ( " MakeCall - AsyncTransmitVc Vc %x", pVc ) );
  443. pVc->Hdr.VcType = NIC1394_SendFIFO;
  444. pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitSendFIFOVc;
  445. pVc->Hdr.VcHandlers.SendPackets = AsyncWriteSendPacketsHandler;
  446. pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallSendFIFO;
  447. break;
  448. }
  449. case TransmitAndReceiveVc:
  450. default:
  451. {
  452. NdisStatus = NDIS_STATUS_FAILURE;
  453. }
  454. }
  455. return NdisStatus;
  456. }
  457. NDIS_STATUS
  458. nicCmGenericMakeCallMutilChannel (
  459. IN PVCCB pVc,
  460. VC_SEND_RECEIVE VcType
  461. )
  462. /*++
  463. Routine Description:
  464. Init the handlers
  465. Arguments:
  466. Return Value:
  467. --*/
  468. {
  469. TRACE( TL_A, TM_Cm, ( "Make Call Recvd for MultiChannel %x ", pVc) );
  470. pVc->Hdr.VcType = NIC1394_MultiChannel;
  471. pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallMultiChannel ;
  472. pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallMultiChannel ;
  473. pVc->Hdr.VcHandlers.SendPackets = AsyncStreamSendPacketsHandler;
  474. return NDIS_STATUS_SUCCESS;
  475. }
  476. NDIS_STATUS
  477. nicCmGenericMakeCallEthernet(
  478. IN PVCCB pVc,
  479. IN VC_SEND_RECEIVE VcType
  480. )
  481. /*++
  482. Routine Description:
  483. Init the handlers
  484. Arguments:
  485. Return Value:
  486. --*/
  487. {
  488. TRACE( TL_A, TM_Cm, ( "Make Call Recvd for Ethernet %x ", pVc) );
  489. pVc->Hdr.VcType = NIC1394_Ethernet;
  490. pVc->Hdr.VcHandlers.MakeCallHandler = nicCmMakeCallInitEthernet;
  491. pVc->Hdr.VcHandlers.SendPackets = nicEthernetVcSend;
  492. pVc->Hdr.VcHandlers.CloseCallHandler = nicCmCloseCallEthernet ;
  493. return NDIS_STATUS_SUCCESS;
  494. }
  495. NDIS_STATUS
  496. nicCmGenericMakeCallInit (
  497. IN PVCCB pVc
  498. )
  499. // Function Description:
  500. //
  501. // This initializes the VcType and Copied the Media Parameters over
  502. // Initialized VCType to SendChannel, RecvChannel, SendAndRecvChanne,
  503. // SendFifo,
  504. //
  505. // Arguments
  506. // Vc - Vc that needs to be initalized
  507. //
  508. // Return Value:
  509. // Success - as no memory allocation takes place
  510. // This function should not do anything that can fail.
  511. {
  512. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  513. VC_SEND_RECEIVE VcType = InvalidType;
  514. PCO_MEDIA_PARAMETERS pMediaParams = pVc->Hdr.pCallParameters->MediaParameters;
  515. PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS) pMediaParams->MediaSpecific.Parameters;
  516. TRACE( TL_T, TM_Cm, ( "==>nicCmGenericMakeCallInit pVc %x", pVc ) );
  517. pVc->Hdr.Nic1394MediaParams = *pN1394Params;
  518. ASSERT(pVc->Hdr.pAF!=NULL);
  519. pVc->Hdr.pGeneration = &pVc->Hdr.pAF->pAdapter->Generation;
  520. //
  521. // Figure out if this is send or receive Vc Or both
  522. //
  523. do
  524. {
  525. if ((pMediaParams->Flags & (TRANSMIT_VC |RECEIVE_VC)) == TRANSMIT_VC)
  526. {
  527. VcType = TransmitVc;
  528. break;
  529. }
  530. if ((pMediaParams->Flags & (TRANSMIT_VC |RECEIVE_VC)) == RECEIVE_VC)
  531. {
  532. VcType = ReceiveVc;
  533. break;
  534. }
  535. if ((pMediaParams->Flags & (TRANSMIT_VC |RECEIVE_VC)) == (TRANSMIT_VC |RECEIVE_VC) )
  536. {
  537. VcType = TransmitAndReceiveVc;
  538. break;
  539. }
  540. } while (FALSE);
  541. ASSERT (VcType <= TransmitAndReceiveVc);
  542. switch (pN1394Params->Destination.AddressType)
  543. {
  544. case NIC1394AddressType_Channel:
  545. {
  546. NdisStatus = nicCmGenericMakeCallInitChannels ((PCHANNEL_VCCB)pVc, VcType);
  547. break;
  548. }
  549. case NIC1394AddressType_FIFO:
  550. {
  551. //
  552. // Now we are in FIFO land.
  553. //
  554. NdisStatus = nicCmGenericMakeCallInitFifo (pVc, VcType );
  555. break;
  556. }
  557. case NIC1394AddressType_MultiChannel:
  558. {
  559. NdisStatus = nicCmGenericMakeCallMutilChannel (pVc, VcType );
  560. break;
  561. }
  562. case NIC1394AddressType_Ethernet:
  563. {
  564. NdisStatus = nicCmGenericMakeCallEthernet(pVc, VcType );
  565. break;
  566. }
  567. default:
  568. {
  569. ASSERT (pN1394Params->Destination.AddressType<=NIC1394AddressType_Ethernet);
  570. NdisStatus = NDIS_STATUS_FAILURE;
  571. break;
  572. }
  573. }
  574. TRACE( TL_T, TM_Cm, ( "<==nicCmGenericMakeCallInit pVc %x, Status %x",pVc , NdisStatus) );
  575. return NdisStatus;
  576. }
  577. VOID
  578. nicCmGenrericMakeCallFailure (
  579. IN PVCCB pVc
  580. )
  581. // Function Description:
  582. // Does the clean up on the VcHDr structure. Will cleanup the Destination, VcType
  583. // and Vc. Initialize Handler. Special case - Recv VC
  584. // Arguments
  585. // PVCCB : Vc on which cleanup need to be done.
  586. // Return Value:
  587. // None
  588. {
  589. TRACE( TL_T, TM_Cm, ( "==>nicGenrericMakeCallFailure pVc %x, ",pVc ) );
  590. //
  591. // First, we need to make sure if adapter's VC is the same as this VC,
  592. // otherwise the adapters'recv VC is Valid Vc currently in Use. Do not touch it.
  593. //
  594. if (pVc->Hdr.VcType == NIC1394_RecvFIFO &&
  595. pVc->Hdr.pAF->pAdapter->pRecvFIFOVc == (PRECVFIFO_VCCB)pVc)
  596. {
  597. //
  598. // This is the reference that was added GenericInitVc function
  599. // and only applied to Recv VC's
  600. //
  601. nicDereferenceVc (pVc);
  602. }
  603. VC_ACQUIRE_LOCK(pVc)
  604. pVc->Hdr.VcHandlers.MakeCallHandler = NULL;
  605. pVc->Hdr.VcHandlers.CloseCallHandler = NULL;
  606. pVc->Hdr.VcType = NIC1394_Invalid_Type;
  607. NdisZeroMemory (&pVc->Hdr.Nic1394MediaParams ,
  608. sizeof (pVc->Hdr.Nic1394MediaParams) );
  609. nicCloseCallRef (pVc);
  610. //
  611. // Mark the Vc Flags, with a MakeCall Failed
  612. //
  613. VC_CLEAR_FLAGS(pVc ,VCBF_MakeCallPending);
  614. VC_SET_FLAG (pVc, VCBF_MakeCallFailed);
  615. VC_RELEASE_LOCK (pVc);
  616. TRACE( TL_T, TM_Cm, ( "<==nicGenrericMakeCallFailure pVc %x, ",pVc ) );
  617. }
  618. VOID
  619. nicCmMakeCallComplete (
  620. NDIS_WORK_ITEM* pMakeCallCompleteWorkItem,
  621. IN PVOID Context
  622. )
  623. // Function:
  624. // This function is used to complete a Make Call. This can be done synchronously
  625. // or asynchronous. If a status pending was passed to this function, it will complete using
  626. // the asynchronous route
  627. //
  628. // If everytrhing succeeds, one Ref to the Vc will be passed through and that will be decremented
  629. // when the call is closed
  630. // This function should never return NDIS_STATUS_PENDING. Will be called as a WorkItem
  631. {
  632. PVCCB pVc = (PVCCB)Context;
  633. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  634. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  635. STORE_CURRENT_IRQL;
  636. TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallComplete ,pVc %x",pVc ) );
  637. //
  638. // Reference the Vc as we want the Vc structure to stay alive till
  639. // the end of the make call complete
  640. //
  641. nicReferenceVc (pVc);
  642. //
  643. // Call the Initialize handler for the VC so that it can be initialized
  644. //
  645. ASSERT (pVc->Hdr.VcHandlers.MakeCallHandler != NULL);
  646. NdisStatus = (*pVc->Hdr.VcHandlers.MakeCallHandler) (pVc);
  647. MATCH_IRQL;
  648. if (NdisStatus == NDIS_STATUS_SUCCESS)
  649. {
  650. VC_ACQUIRE_LOCK(pVc);
  651. //
  652. // Now mark the Vc as active
  653. //
  654. VC_SET_FLAG( pVc, VCBF_VcActivated);
  655. VC_CLEAR_FLAGS(pVc ,VCBF_MakeCallPending);
  656. VC_RELEASE_LOCK (pVc);
  657. }
  658. else
  659. {
  660. //
  661. // call the clean up routine to bring the Vc back to its old state
  662. //
  663. nicCmMakeCallCompleteFailureCleanUp (pVc);
  664. //
  665. // Dereference the call that we are about to fail. This reference was made in
  666. // the beginning of make call routine. when the callref ==0, the Vc will be
  667. // dereferenced as well
  668. //
  669. VC_ACQUIRE_LOCK (pVc);
  670. VC_SET_FLAG (pVc, VCBF_MakeCallFailed);
  671. VC_CLEAR_FLAGS(pVc ,VCBF_MakeCallPending);
  672. nicDereferenceCall (pVc, "nicCmMakeCallComplete");
  673. VC_RELEASE_LOCK (pVc);
  674. }
  675. MATCH_IRQL;
  676. //
  677. // Complete the call with the correct status
  678. //
  679. TRACE( TL_N, TM_Cm, ( "Completing the Make Call , Vc %x, Status %x", pVc, NdisStatus ) );
  680. NdisCmMakeCallComplete(NdisStatus,
  681. pVc->Hdr.NdisVcHandle,
  682. NULL,
  683. NULL,
  684. pVc->Hdr.pCallParameters );
  685. TRACE( TL_I, TM_Cm, ( "Called NdisCmMakeCallComplete, Vc %x, Status%x", pVc, NdisStatus ) );
  686. TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallComplete, Vc %x, Status%x", pVc, NdisStatus ) );
  687. FREE_NONPAGED (pMakeCallCompleteWorkItem);
  688. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  689. //
  690. // This will cause the Vc Refcount to go to zero if the Make Call fails
  691. //
  692. nicDereferenceVc (pVc);
  693. MATCH_IRQL;
  694. }
  695. NDIS_STATUS
  696. nicCmMakeCallInitRecvFIFOVc(
  697. IN OUT PVCCB pVc
  698. )
  699. // Function Description:
  700. //
  701. // This function allocates, packet pool, populates the Slist
  702. // allocates the address range and
  703. // inserts the Vc into the Adapter->pRecvFifoVc field
  704. //
  705. // Will succeed the call, if this process was successful on 1 remote node
  706. // Arguments
  707. // PVCCB : pVc that the call is made on
  708. //
  709. //
  710. // Return Value:
  711. // Success: If all allocations succeeded for just 1 remote node
  712. {
  713. PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB) pVc;
  714. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  715. REMOTE_NODE *pRemoteNode = NULL;
  716. PADAPTERCB pAdapter = pRecvFIFOVc->Hdr.pAF->pAdapter;
  717. PNIC1394_MEDIA_PARAMETERS pN1394Params = &pVc->Hdr.Nic1394MediaParams;
  718. UINT64 UniqueId = pN1394Params->Destination.FifoAddress.UniqueID;
  719. PLIST_ENTRY pPdoListEntry = NULL;
  720. BOOLEAN fWaitSuccessful = FALSE;
  721. BOOLEAN fInitRecvFifoDataStructures = FALSE;
  722. BOOLEAN fNeedToWait = FALSE;
  723. PNIC1394_FIFO_ADDRESS pFifoAddress = NULL;
  724. STORE_CURRENT_IRQL;
  725. TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallInitRecvFIFOVc pRecvFIFOVc %x ", pRecvFIFOVc) );
  726. ASSERT (pAdapter != NULL);
  727. ASSERT (KeGetCurrentIrql()==PASSIVE_LEVEL);
  728. pFifoAddress = &pN1394Params->Destination.FifoAddress;
  729. UniqueId = pFifoAddress->UniqueID;
  730. do
  731. {
  732. NdisStatus = nicInitRecvFifoDataStructures (pRecvFIFOVc);
  733. if (NdisStatus != NDIS_STATUS_SUCCESS)
  734. {
  735. TRACE( TL_A, TM_Cm, ( " nicInitRecvFifoDataStructures FAILED pRecvFIFOVc is %x, UniqueId %I64x ", pRecvFIFOVc) );
  736. break;
  737. }
  738. fInitRecvFifoDataStructures = TRUE;
  739. //
  740. // This field is not used by a RecvFIFO because it has multiple Pdos
  741. //
  742. pRecvFIFOVc->Hdr.pRemoteNode = NULL;
  743. NdisStatus = nicAllocateAddressRange(pAdapter, pRecvFIFOVc);
  744. if(NdisStatus != NDIS_STATUS_SUCCESS)
  745. {
  746. TRACE( TL_A, TM_Cm, ( "Unable to get Pdo and allocate addresses, call FAILED ,pRecvFIFOVc is %x", pRecvFIFOVc) );
  747. ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
  748. break;
  749. }
  750. ASSERT(pRecvFIFOVc->PacketPool.Handle != NULL);
  751. ASSERT(pRecvFIFOVc->Hdr.MTU != 0);
  752. } while (FALSE);
  753. if (NdisStatus != NDIS_STATUS_SUCCESS)
  754. {
  755. //
  756. // Undo all allocated memory
  757. //
  758. TRACE( TL_A, TM_Cm, ( "Failing the Make Call for Vc %x" , pVc) );
  759. if (fInitRecvFifoDataStructures == TRUE)
  760. {
  761. nicUnInitRecvFifoDataStructures (pRecvFIFOVc);
  762. }
  763. }
  764. TRACE( TL_I, TM_Cm, ( "pVc's Offset High %4x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_High ) );
  765. TRACE( TL_I, TM_Cm, ( "pVc's Offset Low %x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_Low ) );
  766. TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallInitRecvFIFOVc %x",NdisStatus ) );
  767. MATCH_IRQL;
  768. return NdisStatus;
  769. }
  770. NDIS_STATUS
  771. nicCmMakeCallInitSendFIFOVc(
  772. IN OUT PVCCB pVc
  773. )
  774. /*++
  775. Routine Description:
  776. This initializes a Send Fifo Make Call.
  777. It
  778. i) finds the remote node using the make call parameters
  779. ii) inititalizes strcutures
  780. Arguments:
  781. pVc - Vc that the make call is done on.
  782. Return Value:
  783. --*/
  784. //
  785. {
  786. PSENDFIFO_VCCB pSendFIFOVc = (PSENDFIFO_VCCB) pVc;
  787. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  788. UINT Generation = 0;
  789. PREMOTE_NODE pRemoteNode = NULL;
  790. PADAPTERCB pAdapter = pSendFIFOVc->Hdr.pAF->pAdapter;
  791. PNIC1394_MEDIA_PARAMETERS pN1394Params = NULL;
  792. UINT64 UniqueId = 0;
  793. PNIC1394_FIFO_ADDRESS pFifoAddress = NULL;
  794. ULONG Speed;
  795. ULONG MaxBufferSize;
  796. ULONG RemoteMaxRec;
  797. BOOLEAN fDeRefRemoteNode = FALSE;
  798. STORE_CURRENT_IRQL;
  799. TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallInitSendFIFOVc pSendFIFOVc %x", pSendFIFOVc ) );
  800. pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pVc->Hdr.pCallParameters->MediaParameters->MediaSpecific.Parameters[0];
  801. ASSERT (pN1394Params->Destination.AddressType == NIC1394AddressType_FIFO);
  802. pFifoAddress = &pN1394Params->Destination.FifoAddress;
  803. UniqueId = pFifoAddress->UniqueID;
  804. TRACE( TL_V, TM_Cm, ( "FifoAddress %x, UniqueId %I64x, Hi %.4x, Lo %x",
  805. pFifoAddress, pFifoAddress->UniqueID,
  806. pFifoAddress->Off_High, pFifoAddress->Off_Low ) );
  807. do
  808. {
  809. //
  810. // Get the Pdo that corresponds with the UniqueId
  811. //
  812. ASSERT(pSendFIFOVc->Hdr.pAF->pAdapter != NULL);
  813. NdisStatus = nicFindRemoteNodeFromAdapter( pSendFIFOVc->Hdr.pAF->pAdapter,
  814. NULL,
  815. UniqueId,
  816. &pRemoteNode);
  817. if(NdisStatus != NDIS_STATUS_SUCCESS)
  818. {
  819. TRACE( TL_A, TM_Cm, ( "Unable to Find Pdo, call FAILED ,pSendFIFOVc is %x, UniqueId %I64x ", pSendFIFOVc, UniqueId ) );
  820. break;
  821. }
  822. ASSERT (pRemoteNode != NULL);
  823. //
  824. // nicFindRemoteNodeFromAdapter ref's pRemoteNode on success.
  825. // We need to deref it if we're not going to be using it.
  826. // Let's start by assuming we aren't.
  827. //
  828. fDeRefRemoteNode = TRUE;
  829. //
  830. // Get the Generation Count of the device
  831. //
  832. NdisStatus = nicGetGenerationCount ( pRemoteNode->pAdapter, &Generation);
  833. if(NdisStatus != NDIS_STATUS_SUCCESS)
  834. {
  835. TRACE( TL_A, TM_Cm, ( "GET GENERATION FAILED ,pSendFIFOVc is %x", pSendFIFOVc ) );
  836. ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
  837. break;
  838. }
  839. TRACE( TL_V, TM_Cm, ( "Found PdoCb %x for pSendFIFOVc %x", pRemoteNode,pSendFIFOVc ) );
  840. //
  841. // We check if the remote node's pdo is active. if so, then insert the Vc into the
  842. // PdoCb's list. Now responsibility for any removals has moved to the remove remote node code path
  843. //
  844. //
  845. // Get the max buffer size that can be transmitted on this link
  846. //
  847. NdisStatus = nicQueryRemoteNodeCaps (pAdapter,
  848. pRemoteNode,
  849. // FALSE, // FALSE== not from cache.
  850. &Speed,
  851. &MaxBufferSize,
  852. &RemoteMaxRec);
  853. if (NdisStatus != NDIS_STATUS_SUCCESS)
  854. {
  855. break;
  856. }
  857. ADAPTER_ACQUIRE_LOCK (pAdapter);
  858. if (REMOTE_NODE_ACTIVE (pRemoteNode) == FALSE)
  859. {
  860. NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
  861. ADAPTER_RELEASE_LOCK (pAdapter);
  862. break;
  863. }
  864. //
  865. // Reference the call in the Vc as the RemoteNodePdo is about to have a pointer to it., This is dereferenced
  866. // in the CloseCallComplete Send Fifo Function. we have the lock
  867. //
  868. nicReferenceCall (pVc, "nicCmMakeCallInitSendFIFOVc");
  869. //
  870. // We keep the reference to pRemoteNode that was added by FindRemoteNode.
  871. // Derefed in SendFifoCloseCall when the pointer is nulled
  872. //
  873. fDeRefRemoteNode = FALSE;
  874. //
  875. // Insert the Vc into the Pdo's List
  876. //
  877. InsertTailList (&pRemoteNode->VcList, &pSendFIFOVc->Hdr.SinglePdoVcLink);
  878. TRACE( TL_V, TM_Cm, ( "Inserted Vc %x into Pdo List %x ", pSendFIFOVc, pRemoteNode) );
  879. //
  880. // This is not protected by the lock, but we are gauranteed that the Call will not be closed
  881. // and the Pdo will not be be removed from the system at this point, So we can update
  882. // this field.
  883. //
  884. pSendFIFOVc->Hdr.pRemoteNode = pRemoteNode;
  885. ADAPTER_RELEASE_LOCK (pAdapter);
  886. //
  887. // Acquire the spin lock and initialize the structures
  888. //
  889. VC_ACQUIRE_LOCK (pSendFIFOVc);
  890. pSendFIFOVc->Hdr.MTU = pN1394Params->MTU;
  891. pSendFIFOVc->Hdr.pGeneration = &pAdapter->Generation;
  892. pSendFIFOVc->FifoAddress = pN1394Params->Destination.FifoAddress;
  893. pSendFIFOVc->MaxSendSpeed = pN1394Params->MaxSendSpeed;
  894. pSendFIFOVc->Hdr.MaxPayload = min (pN1394Params->MTU, (ULONG)pN1394Params->MaxSendBlockSize);
  895. VC_RELEASE_LOCK (pSendFIFOVc);
  896. //
  897. // Validate the parameters for the Vc
  898. //
  899. ASSERT(pSendFIFOVc->Hdr.pRemoteNode != NULL);
  900. ASSERT(pSendFIFOVc->Hdr.pRemoteNode->pPdo != NULL);
  901. ASSERT(pSendFIFOVc->Hdr.pGeneration != NULL);
  902. ASSERT(pSendFIFOVc->MaxSendSpeed != 0);
  903. ASSERT(pSendFIFOVc->Hdr.MTU != 0);
  904. TRACE( TL_V, TM_Cm, ( " Generation is %x", *pSendFIFOVc->Hdr.pGeneration ) );
  905. TRACE( TL_N, TM_Cm, ( " Pdo in the Send VC is %x", pSendFIFOVc->Hdr.pRemoteNode->pPdo) );
  906. if (NdisStatus != NDIS_STATUS_SUCCESS)
  907. {
  908. break;
  909. }
  910. pSendFIFOVc->MaxSendSpeed = min(pSendFIFOVc->MaxSendSpeed,Speed);
  911. pSendFIFOVc->Hdr.MaxPayload = min (pSendFIFOVc->Hdr.MaxPayload, MaxBufferSize);
  912. #ifdef LOWER_SEND_SPEED
  913. pSendFIFOVc->MaxSendSpeed = SCODE_200_RATE;//min(pSendFIFOVc->MaxSendSpeed,Speed);
  914. pSendFIFOVc->Hdr.MaxPayload = ASYNC_PAYLOAD_200_RATE ;// min(pSendFIFOVc->Hdr.MaxPayload, MaxBufferSize);
  915. #endif
  916. TRACE( TL_V, TM_Cm, ( " MaxSendSpeed is %x", pSendFIFOVc->MaxSendSpeed) );
  917. TRACE( TL_V, TM_Cm, ( " MaxPayload is %d", pSendFIFOVc->Hdr.MaxPayload ) );
  918. } while (FALSE);
  919. if ( NdisStatus != NDIS_STATUS_SUCCESS)
  920. {
  921. //
  922. // The Make is going to be failed asynchrnously
  923. // If we allocated in resources, we must free them
  924. // In this case, there have been no Resources allocated
  925. //
  926. }
  927. TRACE( TL_I, TM_Cm, ( " pVc's Offset High %4x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_High ) );
  928. TRACE( TL_I, TM_Cm, ( " pVc's Offset Low %x",pVc->Hdr.Nic1394MediaParams.Destination.FifoAddress.Off_Low ) );
  929. TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallInitSendFIFOVc %x",NdisStatus ) );
  930. if (fDeRefRemoteNode)
  931. {
  932. nicDereferenceRemoteNode (pRemoteNode, FindRemoteNodeFromAdapterFail);
  933. }
  934. MATCH_IRQL;
  935. return NdisStatus;
  936. }
  937. NDIS_STATUS
  938. nicCmMakeCallInitSendRecvChannelVc(
  939. IN OUT PVCCB pVc
  940. )
  941. // Function Description:
  942. //
  943. // Arguments
  944. // pVc, This is the send fifo that needs to be initilaized
  945. //
  946. //
  947. // Return Value:
  948. //
  949. // Success if the irps sent to the driver succeed
  950. //
  951. //
  952. {
  953. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
  954. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  955. PNIC1394_MEDIA_PARAMETERS pN1394Params = NULL;
  956. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  957. ULONG Channel = 64;
  958. HANDLE hResource=NULL;
  959. ULONG MaxBufferSize = 0;
  960. ULONG QuadletsToStrip = 0;
  961. PISOCH_DESCRIPTOR pIsochDescriptor = NULL;
  962. CYCLE_TIME CycleTime;
  963. PDEVICE_OBJECT ArrayRemotePDO[64];
  964. //NDIS_HANDLE hPacketPoolHandle=NULL;
  965. BOOLEAN fAnyChannel = FALSE;
  966. NIC_PACKET_POOL PacketPool;
  967. STORE_CURRENT_IRQL;
  968. TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallInitSendRecvChannelVc pVc %x", pVc ) );
  969. ASSERT (pAdapter != NULL);
  970. pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pVc->Hdr.pCallParameters->MediaParameters->MediaSpecific.Parameters[0];
  971. Channel = pN1394Params->Destination.Channel;
  972. TRACE( TL_V, TM_Cm, ( "Channel %x", Channel ) );
  973. do
  974. {
  975. PacketPool.Handle = NULL;
  976. ADAPTER_ACQUIRE_LOCK( pAdapter );
  977. //
  978. // Set up the the VDO, so that all channel operations can use it
  979. //
  980. pVc->Hdr.pLocalHostVDO = pAdapter->pNextDeviceObject;
  981. ADAPTER_RELEASE_LOCK( pAdapter );
  982. NdisAllocatePacketPoolEx ( &NdisStatus,
  983. &PacketPool.Handle,
  984. MIN_PACKET_POOL_SIZE,
  985. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  986. sizeof (RSVD) );
  987. if (PacketPool.Handle == NULL || NdisStatus != NDIS_STATUS_SUCCESS)
  988. {
  989. BREAK (TM_Cm, ( "NdisAllocatePacketPoolEx FAILED" ) );
  990. }
  991. //
  992. // Reference Call for Packet Pool Handle
  993. //
  994. nicReferenceCall ((PVCCB)pChannelVc, "nicCmMakeCallInitSendRecvChannelVc - packet pool ");
  995. PacketPool.AllocatedPackets = 0;
  996. pChannelVc->Hdr.MTU = pN1394Params->MTU;
  997. pChannelVc->PacketPool= PacketPool;
  998. NdisInitializeEvent(&pChannelVc->LastDescReturned);
  999. //
  1000. // This function should do its own cleanup
  1001. //
  1002. NdisStatus = nicAllocateChannelResourcesAndListen (pAdapter,
  1003. pChannelVc );
  1004. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1005. {
  1006. BREAK (TM_Cm, ( "nicAllocateChannelResourcesAndListen FAILED" ) );
  1007. }
  1008. //
  1009. // Return the allocated channel number, if this is an any channel
  1010. // or broadcast channel call
  1011. //
  1012. if ((pN1394Params->Destination.Channel == NIC1394_ANY_CHANNEL) &&
  1013. (pN1394Params->Destination.AddressType == NIC1394AddressType_Channel))
  1014. {
  1015. pN1394Params->Destination.Channel = pChannelVc->Channel;
  1016. }
  1017. //
  1018. // Make the same change for broadcast channels
  1019. //
  1020. if ((pN1394Params->Destination.Channel == NIC1394_BROADCAST_CHANNEL) &&
  1021. (pN1394Params->Destination.AddressType == NIC1394AddressType_Channel))
  1022. {
  1023. pN1394Params->Destination.Channel = pChannelVc->Channel;
  1024. }
  1025. } while (FALSE);
  1026. //
  1027. // Time to do clean up based on what resources were allocated
  1028. //
  1029. if (NdisStatus != NDIS_STATUS_SUCCESS )
  1030. {
  1031. //Undo all resources acquired
  1032. if (PacketPool.Handle != NULL)
  1033. {
  1034. //
  1035. // Free the pool
  1036. //
  1037. nicFreePacketPool(&PacketPool);
  1038. nicDereferenceCall ((PVCCB)pChannelVc, "nicCmMakeCallInitSendRecvChannelVc - packet pool ");
  1039. NdisZeroMemory (&pChannelVc->PacketPool, sizeof (pChannelVc->PacketPool));
  1040. }
  1041. //
  1042. // Do not decrement any ref counts because if Status != success
  1043. // then we have not incremented refcounts.
  1044. //
  1045. }
  1046. TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallInitSendRecvChannelVc %x", NdisStatus) );
  1047. return NdisStatus;
  1048. }
  1049. NDIS_STATUS
  1050. nicCmMakeCallInitEthernet (
  1051. IN PVCCB pVc
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. Do nothing for now. Just succeed
  1056. Arguments:
  1057. Return Value:
  1058. --*/
  1059. {
  1060. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1061. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1062. PETHERNET_VCCB pEthernetVc = (PETHERNET_VCCB)pVc;
  1063. NIC_PACKET_POOL PacketPool;
  1064. TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallInitEthernet %x", pVc) );
  1065. do
  1066. {
  1067. PacketPool.Handle = NULL;
  1068. //
  1069. // Initialize the PacketPool
  1070. //
  1071. NdisAllocatePacketPoolEx ( &NdisStatus,
  1072. &PacketPool.Handle,
  1073. MIN_PACKET_POOL_SIZE,
  1074. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  1075. sizeof (RSVD) );
  1076. if (NdisStatus!= NDIS_STATUS_SUCCESS)
  1077. {
  1078. ASSERT(NdisStatus != NDIS_STATUS_SUCCESS);
  1079. pEthernetVc->PacketPool.Handle = NULL;
  1080. PacketPool.Handle = NULL;
  1081. break;
  1082. }
  1083. NdisStatus = NDIS_STATUS_SUCCESS;
  1084. //
  1085. // No more failures
  1086. //
  1087. nicReferenceCall ((PVCCB)pEthernetVc, "Alloc PacketPool - Ethernet VC " ) ;
  1088. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1089. //
  1090. // Reference the VC as the adapter has a pointer to it
  1091. //
  1092. nicReferenceCall (pVc, "nicCmMakeCallEthernet ");
  1093. pAdapter->pEthernetVc = (PETHERNET_VCCB)pVc;
  1094. pEthernetVc->PacketPool= PacketPool;
  1095. pEthernetVc->PacketPool.AllocatedPackets = 0;
  1096. ADAPTER_RELEASE_LOCK (pAdapter);
  1097. } while (FALSE);
  1098. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1099. {
  1100. if (PacketPool.Handle != NULL)
  1101. {
  1102. //
  1103. // Free the pool
  1104. //
  1105. nicFreePacketPool(&PacketPool);
  1106. }
  1107. }
  1108. TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallEthernet %x", NdisStatus) );
  1109. return NdisStatus;
  1110. }
  1111. NDIS_STATUS
  1112. nicCmMakeCallMultiChannel (
  1113. IN PVCCB pVc
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. Do whatever the channel Vc does
  1118. Arguments:
  1119. Return Value:
  1120. --*/
  1121. {
  1122. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1123. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1124. PCHANNEL_VCCB pMcVc = (PCHANNEL_VCCB)pVc;
  1125. NIC_PACKET_POOL PacketPool;
  1126. TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallMultiChannel %x", pVc) );
  1127. do
  1128. {
  1129. PacketPool.Handle = NULL;
  1130. //
  1131. // Initialize the PacketPool
  1132. //
  1133. NdisAllocatePacketPoolEx ( &NdisStatus,
  1134. &PacketPool.Handle,
  1135. MIN_PACKET_POOL_SIZE,
  1136. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  1137. sizeof (RSVD) );
  1138. if (NdisStatus!= NDIS_STATUS_SUCCESS)
  1139. {
  1140. ASSERT(NdisStatus != NDIS_STATUS_SUCCESS);
  1141. pMcVc->PacketPool.Handle = NULL;
  1142. break;
  1143. }
  1144. NdisStatus = NDIS_STATUS_SUCCESS;
  1145. //
  1146. // No more failures
  1147. //
  1148. nicReferenceCall ((PVCCB)pMcVc, "Alloc PacketPool - MultiChannel VC " ) ;
  1149. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1150. pMcVc->PacketPool= PacketPool;
  1151. pMcVc->PacketPool.AllocatedPackets = 0;
  1152. pMcVc->Hdr.MTU = pMcVc->Hdr.Nic1394MediaParams.MTU;
  1153. ADAPTER_RELEASE_LOCK (pAdapter);
  1154. if (pMcVc->Hdr.Nic1394MediaParams.Destination.ChannnelMap.QuadPart == 0)
  1155. {
  1156. pMcVc->Channel = 0xff;
  1157. NdisStatus = NDIS_STATUS_SUCCESS;
  1158. break;
  1159. }
  1160. //
  1161. // This portion Not Implemented yet. ChannelMap != 0
  1162. // Should use nicAllocateResourcesAndListen after updating the
  1163. // Nic1394MediaParams to make it look like a regular ChannelMake Call
  1164. //
  1165. NdisStatus = NDIS_STATUS_FAILURE;
  1166. ASSERT (0);
  1167. } while (FALSE);
  1168. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1169. {
  1170. if (PacketPool.Handle != NULL)
  1171. {
  1172. //
  1173. // Free the pool
  1174. //
  1175. nicFreePacketPool(&PacketPool);
  1176. }
  1177. }
  1178. TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallMultiChannel %x", NdisStatus) );
  1179. return NdisStatus;
  1180. }
  1181. NDIS_STATUS
  1182. nicCmMakeCallSendChannel (
  1183. IN PVCCB pVc
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This function allocates the channel but does nothing else.
  1188. It is only used to send data and therefore needs no other data
  1189. It needs to update pChannelVc->Channel; ulSynch; Speed;
  1190. all of which are needed to do an AsyncStream Irb
  1191. Arguments:
  1192. Return Value:
  1193. --*/
  1194. {
  1195. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1196. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
  1197. BOOLEAN fNeedToAllocate = VC_TEST_FLAG (pChannelVc, VCBF_NeedsToAllocateChannel);
  1198. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1199. ULONG Speed = 0;
  1200. UINT MaxPacketSize = 0;
  1201. PNIC1394_MEDIA_PARAMETERS pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pChannelVc->Hdr.Nic1394MediaParams;
  1202. ULONG Channel = pN1394Params->Destination.Channel;
  1203. TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallSendChannel pVc %x", pVc) );
  1204. do
  1205. {
  1206. //
  1207. // Allocate the channel
  1208. //
  1209. if (fNeedToAllocate == TRUE)
  1210. {
  1211. NdisStatus = nicAllocateRequestedChannelMakeCallComplete (pAdapter,
  1212. pChannelVc,
  1213. &Channel);
  1214. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1215. {
  1216. BREAK (TM_Cm, ("Unable to allocate Channel on Send Only Vc" ) );
  1217. }
  1218. }
  1219. //
  1220. // Find out the Speed.
  1221. //
  1222. if (pAdapter->Speed == 0)
  1223. {
  1224. nicUpdateLocalHostSpeed (pAdapter);
  1225. }
  1226. pChannelVc->Speed = pAdapter->Speed;
  1227. Speed = pAdapter->Speed;
  1228. switch (pChannelVc->Speed)
  1229. {
  1230. case SPEED_FLAGS_100 :
  1231. {
  1232. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_100_RATE;
  1233. break;
  1234. }
  1235. case SPEED_FLAGS_200 :
  1236. {
  1237. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_200_RATE ;
  1238. break;
  1239. }
  1240. case SPEED_FLAGS_400 :
  1241. {
  1242. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  1243. break;
  1244. }
  1245. case SPEED_FLAGS_800:
  1246. {
  1247. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  1248. break;
  1249. }
  1250. case SPEED_FLAGS_1600:
  1251. {
  1252. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  1253. break;
  1254. }
  1255. case SPEED_FLAGS_3200 :
  1256. {
  1257. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  1258. break;
  1259. }
  1260. default :
  1261. {
  1262. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  1263. break;
  1264. }
  1265. }
  1266. pChannelVc->Channel = Channel ;
  1267. MaxPacketSize = min(pN1394Params->MTU + sizeof(GASP_HEADER) , pChannelVc->Hdr.MaxPayload);
  1268. //
  1269. // If broadcast channel, then decrease the speed setting, and fragment
  1270. //
  1271. pChannelVc->Channel = Channel;
  1272. pChannelVc->MaxBufferSize = 0;
  1273. pChannelVc->Speed = Speed;
  1274. pChannelVc->Hdr.MaxPayload = MaxPacketSize;
  1275. pChannelVc->Hdr.MTU = pN1394Params->MTU ;
  1276. pChannelVc->NumDescriptors = 0;
  1277. pChannelVc->pIsochDescriptor = NULL;
  1278. NdisStatus = NDIS_STATUS_SUCCESS;
  1279. } while (FALSE);
  1280. TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallSendChannel %x", NdisStatus) );
  1281. return NdisStatus;
  1282. }
  1283. VOID
  1284. nicCmMakeCallCompleteFailureCleanUp(
  1285. IN OUT PVCCB pVc
  1286. )
  1287. // Function Description:
  1288. // This function cleans up, if the makecallcomplete fails for whatever reason.
  1289. // Maybe this should be split up as well
  1290. // In the RecvFIFOVc case: it needs to deallocate the Slist and PacketPool,
  1291. // Common:
  1292. // Also delete the VcType and nic1394 destination in the Vc Hdr
  1293. // Arguments
  1294. // PVCCB pVc - Vc that needs to be cleaned up
  1295. //
  1296. // Return Value:
  1297. //
  1298. //
  1299. {
  1300. STORE_CURRENT_IRQL;
  1301. TRACE( TL_T, TM_Cm, ( "==>nicCmMakeCallCompleteFailureCleanUp pVc %x", pVc ) );
  1302. switch (pVc->Hdr.VcType)
  1303. {
  1304. case NIC1394_RecvFIFO:
  1305. {
  1306. PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB )pVc;
  1307. TRACE( TL_V, TM_Cm, ( "Cleaning up a recv FIFo %x", pVc ) );
  1308. if (pRecvFIFOVc->PacketPool.Handle != NULL)
  1309. {
  1310. nicFreePacketPool (&pRecvFIFOVc->PacketPool);
  1311. }
  1312. pRecvFIFOVc->PacketPool.Handle = NULL;
  1313. if (pRecvFIFOVc->FifoSListHead.Alignment != 0)
  1314. {
  1315. nicFreeAllocateAddressRangeSList (pRecvFIFOVc);
  1316. }
  1317. pRecvFIFOVc->FifoSListHead.Alignment = 0;
  1318. break;
  1319. }
  1320. case NIC1394_SendFIFO:
  1321. case NIC1394_SendRecvChannel:
  1322. case NIC1394_SendChannel:
  1323. case NIC1394_RecvChannel:
  1324. default:
  1325. break;
  1326. }
  1327. //
  1328. // This call does the generic clean up
  1329. //
  1330. nicCmGenrericMakeCallFailure (pVc);
  1331. TRACE( TL_T, TM_Cm, ( "<==nicCmMakeCallCompleteFailureCleanUp ") );
  1332. MATCH_IRQL;
  1333. return ;
  1334. }
  1335. NDIS_STATUS
  1336. NicCmCloseCall(
  1337. IN NDIS_HANDLE CallMgrVcContext,
  1338. IN NDIS_HANDLE CallMgrPartyContext,
  1339. IN PVOID CloseData,
  1340. IN UINT Size )
  1341. // Standard 'CmCloseCallHandler' routine called by NDIS when the a client
  1342. // has requested to tear down a call. See DDK doc.
  1343. //
  1344. {
  1345. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1346. ADAPTERCB* pAdapter = NULL;
  1347. VCCB* pVc = NULL;
  1348. NDIS_WORK_ITEM* pCloseCallCompleteWorkItem = NULL;
  1349. STORE_CURRENT_IRQL;
  1350. TRACE( TL_T, TM_Cm, ( "==>NicCmCloseCall($%p)", CallMgrVcContext ) );
  1351. pVc = (VCCB* )CallMgrVcContext;
  1352. if (pVc->Hdr.ulTag != MTAG_VCCB)
  1353. {
  1354. ASSERT( !"Vtag?" );
  1355. return NDIS_STATUS_INVALID_DATA;
  1356. }
  1357. do
  1358. {
  1359. pAdapter = pVc->Hdr.pAF->pAdapter;
  1360. if (pAdapter == NULL)
  1361. {
  1362. TRACE( TL_A, TM_Cm, ( "pAdpater is NULL - Make Call FAILED($%p)", CallMgrVcContext ) );
  1363. NdisStatus = NDIS_STATUS_FAILURE;
  1364. break;
  1365. }
  1366. VC_ACQUIRE_LOCK (pVc);
  1367. //
  1368. // If the Make Call is Pending, then fail the CloseCall.
  1369. // Or if there call is already closing then fail this close call
  1370. //
  1371. if ( VC_ACTIVE (pVc) == FALSE )
  1372. {
  1373. TRACE( TL_A, TM_Cm, ( "NicCmCloseCall Invalid flags - Close Call FAILED Vc $%p, flags %x", pVc, pVc->Hdr.ulFlags ) );
  1374. ASSERT ( ! "MakeCallPending or Call already closed?");
  1375. VC_RELEASE_LOCK (pVc);
  1376. break;
  1377. }
  1378. //
  1379. //
  1380. // Reference the Vc so we can gaurantee its presence till the end of the work item
  1381. // to CloseCallComplete. we have the lock
  1382. //
  1383. nicReferenceVc (pVc);
  1384. //
  1385. // Mark the Call as closing, and close the refcount, so no one can increment it
  1386. //
  1387. VC_SET_FLAG ( pVc, VCBF_CloseCallPending);
  1388. nicCloseCallRef (pVc);
  1389. VC_RELEASE_LOCK (pVc);
  1390. pCloseCallCompleteWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  1391. if (pCloseCallCompleteWorkItem == NULL)
  1392. {
  1393. TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem - Close Call FAILED($%p)", CallMgrVcContext ) );
  1394. NdisStatus = NDIS_STATUS_RESOURCES;
  1395. break;
  1396. }
  1397. NdisInitializeWorkItem ( pCloseCallCompleteWorkItem,
  1398. (NDIS_PROC)nicCmCloseCallComplete,
  1399. (PVOID)pVc );
  1400. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  1401. NdisScheduleWorkItem (pCloseCallCompleteWorkItem);
  1402. NdisStatus = NDIS_STATUS_PENDING;
  1403. } while (FALSE);
  1404. MATCH_IRQL;
  1405. TRACE( TL_T, TM_Cm, ( "<==NicCmCloseCall pending" ) );
  1406. return NdisStatus;
  1407. }
  1408. VOID
  1409. nicCmCloseCallComplete(
  1410. NDIS_WORK_ITEM* pCloseCallCompleteWorkItem,
  1411. IN PVOID Context
  1412. )
  1413. // Function Description:
  1414. // This function completes the close call. The qor Item gaurantees that all work will be
  1415. // done at passive level
  1416. //
  1417. // Arguments
  1418. // Context : Which is VCCB for which the close call was requested
  1419. //
  1420. //
  1421. // Return Value:
  1422. // None
  1423. // However an NdisStatus is passed in the call to Ndis' close call complete function
  1424. //
  1425. //
  1426. {
  1427. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1428. PVCCB pVc = (PVCCB) Context;
  1429. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1430. BOOLEAN fCallClosable = FALSE;
  1431. BOOLEAN fWaitSucceeded = FALSE;
  1432. STORE_CURRENT_IRQL;
  1433. TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallComplete pVc %x", pVc ) );
  1434. //
  1435. // Invoke the close call handler of the VC
  1436. //
  1437. ASSERT (pVc->Hdr.VcHandlers.CloseCallHandler != NULL);
  1438. NdisStatus = (*pVc->Hdr.VcHandlers.CloseCallHandler) (pVc);
  1439. //
  1440. // right now, we do not fail a close call because the bus driver failed us.
  1441. //
  1442. NdisStatus = NDIS_STATUS_SUCCESS;
  1443. //
  1444. // Made it so far, we now need to dereference the call. We made the reference in
  1445. // MakeCall. This will complete the call if it gets down to zero
  1446. //
  1447. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1448. {
  1449. //
  1450. // Derefercence the call ref and Vc Refs that were added at the end of
  1451. // a successful make call
  1452. //
  1453. nicDereferenceCall (pVc, "nicCmCloseCallComplete");
  1454. }
  1455. //
  1456. // Important : THIS WAIT is for the REFCOUNT on the CALL , not the VC
  1457. //
  1458. TRACE( TL_N, TM_Cm, ( "About to Wait for CallRefs to go to zero pVc %x ", pVc) );
  1459. fWaitSucceeded = NdisWaitEvent (&pVc->Hdr.CallRef.RefZeroEvent, WAIT_INFINITE );
  1460. if (fWaitSucceeded == FALSE)
  1461. {
  1462. TRACE( TL_A, TM_Cm, ( "Wait Timed Out Call, Vc %x, RefCount %x ", pVc , pVc->Hdr.CallRef.ReferenceCount) );
  1463. ASSERT (fWaitSucceeded == TRUE);
  1464. }
  1465. ASSERT (KeGetCurrentIrql() <= DISPATCH_LEVEL);
  1466. //
  1467. // Succeed the Close call as all references have gone to zero
  1468. // The call has no more outstanding resources
  1469. //
  1470. TRACE( TL_N, TM_Cm, ( "About to Close Call on pVc %x", pVc ) );
  1471. NdisMCmCloseCallComplete( NDIS_STATUS_SUCCESS,
  1472. pVc->Hdr.NdisVcHandle, NULL );
  1473. VC_ACQUIRE_LOCK (pVc);
  1474. VC_CLEAR_FLAGS (pVc, VCBF_CloseCallPending);
  1475. VC_SET_FLAG (pVc, VCBF_CloseCallCompleted);
  1476. VC_RELEASE_LOCK (pVc);
  1477. FREE_NONPAGED (pCloseCallCompleteWorkItem);
  1478. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  1479. //
  1480. // Release the reference made when entering the Close Call function above. so the Vc can disappear if it wants to
  1481. // Remember that delete Vc can already have gone through at this time, and the Vc will be freed after the deref
  1482. //
  1483. nicDereferenceVc (pVc);
  1484. TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallComplete pVc %x, Status %x", pVc, NdisStatus ) );
  1485. MATCH_IRQL;
  1486. }
  1487. NDIS_STATUS
  1488. nicCmCloseCallEthernet (
  1489. IN PVCCB pVc
  1490. )
  1491. /*++
  1492. Routine Description:
  1493. Do nothing for now. Just succeed
  1494. Arguments:
  1495. Return Value:
  1496. --*/
  1497. {
  1498. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1499. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1500. PETHERNET_VCCB pEthernetVc = (PETHERNET_VCCB)pVc;
  1501. NIC_PACKET_POOL PacketPool;
  1502. TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallEthernet %x", pVc) );
  1503. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1504. PacketPool = pEthernetVc->PacketPool;
  1505. pEthernetVc->PacketPool.Handle = 0;
  1506. pEthernetVc->PacketPool.AllocatedPackets = 0;
  1507. ADAPTER_RELEASE_LOCK (pAdapter);
  1508. if (PacketPool.Handle != NULL)
  1509. {
  1510. nicDereferenceCall ((PVCCB)pEthernetVc, "pEthernetVc - Free PacketPool" );
  1511. nicFreePacketPool (&PacketPool);
  1512. }
  1513. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1514. //
  1515. // Dereference the VC as the adapter's pointer has been cleared
  1516. //
  1517. nicDereferenceCall (pVc, "nicCmMakeCallEthernet ");
  1518. pAdapter->pEthernetVc = NULL;
  1519. ADAPTER_RELEASE_LOCK (pAdapter);
  1520. NdisStatus = NDIS_STATUS_SUCCESS;
  1521. TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallEthernet %x", NdisStatus) );
  1522. return NdisStatus;
  1523. }
  1524. NDIS_STATUS
  1525. nicCmCloseCallMultiChannel (
  1526. IN PVCCB pVc
  1527. )
  1528. /*++
  1529. Routine Description:
  1530. Free the packet pool and Just succeed
  1531. Arguments:
  1532. Return Value:
  1533. --*/
  1534. {
  1535. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1536. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1537. PCHANNEL_VCCB pMcVc = (PCHANNEL_VCCB)pVc;
  1538. NIC_PACKET_POOL PacketPool;
  1539. TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallMultiChannel %x", pVc) );
  1540. ASSERT (VC_TEST_FLAG (pVc, VCBF_BroadcastVc) == FALSE);
  1541. //
  1542. // Mask the fact that this is a multichannel Call
  1543. //
  1544. NdisStatus = nicCmCloseCallSendRecvChannel (pVc);
  1545. //
  1546. // Nothing to fail
  1547. //
  1548. NdisStatus = NDIS_STATUS_SUCCESS;
  1549. TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallMultiChannel %x", NdisStatus) );
  1550. return NdisStatus;
  1551. }
  1552. NDIS_STATUS
  1553. nicCmCloseCallSendRecvChannel (
  1554. IN PVCCB pVc
  1555. )
  1556. // Function Description:
  1557. // This function will do clean up for RecvFifos
  1558. // Includes removing the VC pointer from Pdo Adapter structure.
  1559. // And needs to go through all active remote nodes and free the address ranges on them
  1560. // The BCM Vc has the added overhead of having an address range associated with it.
  1561. // which we need to free
  1562. //
  1563. // Arguments
  1564. // PVCCB pVc - The Channel VC that needs to be closed
  1565. //
  1566. // Return Value:
  1567. // Success for now
  1568. //
  1569. // Called with the lock held
  1570. {
  1571. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB ) pVc;
  1572. PCHANNEL_VCCB pTempVc = NULL;
  1573. BOOLEAN fIsBroadcastVc = FALSE;
  1574. PLIST_ENTRY pVcListEntry = NULL;
  1575. PADAPTERCB pAdapter = NULL;
  1576. ULONG NumDereferenced ;
  1577. HANDLE hResource ;
  1578. ULONG NumDescriptors ;
  1579. PISOCH_DESCRIPTOR pIsochDescriptor;
  1580. BOOLEAN fAllocatedChannel ;
  1581. ULONG Channel ;
  1582. NIC_PACKET_POOL PacketPool;
  1583. STORE_CURRENT_IRQL;
  1584. TRACE( TL_T, TM_Cm, ( "==> nicCmCloseCallSendRecvChannel pVc %x", pVc) );
  1585. ASSERT (pVc!=NULL);
  1586. pAdapter = pChannelVc->Hdr.pAF->pAdapter;
  1587. ASSERT (pAdapter != NULL);
  1588. do
  1589. {
  1590. VC_ACQUIRE_LOCK (pChannelVc);
  1591. if (VC_TEST_FLAG (pChannelVc, VCBF_BroadcastVc) == TRUE)
  1592. {
  1593. PADDRESS_RANGE_CONTEXT pBCRAddress = &pAdapter->BCRData.AddressRangeContext;
  1594. //
  1595. // Free the allocated address renge for the Broadcast Channel Register
  1596. //
  1597. if ( BCR_TEST_FLAG (pAdapter, BCR_Initialized) == TRUE)
  1598. {
  1599. //
  1600. // Clear out the Broadcast VC in the BCRData structure, Derereference the call. and clear the flag
  1601. // The ref was made in the MakeCallAllocateChannel function
  1602. //
  1603. if (pAdapter->BCRData.pBroadcastChanneVc != NULL)
  1604. {
  1605. pAdapter->BCRData.pBroadcastChanneVc = NULL;
  1606. nicDereferenceCall((PVCCB) pChannelVc, "nicCmCloseCallSendRecvChannel Broadcast VC");
  1607. }
  1608. VC_CLEAR_FLAGS (pChannelVc, VCBF_BroadcastVc) ;
  1609. }
  1610. }
  1611. VC_RELEASE_LOCK (pChannelVc);
  1612. nicIsochStop (pAdapter,
  1613. pChannelVc->hResource);
  1614. VC_ACQUIRE_LOCK (pChannelVc);
  1615. PacketPool = pChannelVc->PacketPool;
  1616. hResource = pChannelVc->hResource;
  1617. NumDescriptors = pChannelVc->NumDescriptors;
  1618. pIsochDescriptor = pChannelVc->pIsochDescriptor;
  1619. fAllocatedChannel = VC_TEST_FLAGS( pChannelVc, VCBF_AllocatedChannel);
  1620. Channel = pChannelVc->Channel;
  1621. PacketPool = pChannelVc->PacketPool;
  1622. //
  1623. // Clean out the VC structure and then call NDIS or the bus driver to free all
  1624. // the resources
  1625. //
  1626. nicChannelCallCleanDataStructure (pChannelVc,
  1627. pChannelVc->hResource,
  1628. pChannelVc->NumDescriptors,
  1629. pChannelVc->pIsochDescriptor,
  1630. fAllocatedChannel,
  1631. pChannelVc->Channel,
  1632. pChannelVc->PacketPool.Handle,
  1633. &NumDereferenced );
  1634. VC_RELEASE_LOCK (pChannelVc);
  1635. nicChannelCallFreeResources ( pChannelVc,
  1636. pAdapter,
  1637. hResource,
  1638. NumDescriptors,
  1639. pIsochDescriptor,
  1640. fAllocatedChannel,
  1641. Channel,
  1642. &PacketPool);
  1643. } while (FALSE);
  1644. TRACE( TL_T, TM_Cm, ( "<== nicCmCloseCallSendRecvChannel Status %x(always success)" ) );
  1645. MATCH_IRQL;
  1646. return NDIS_STATUS_SUCCESS;
  1647. }
  1648. NDIS_STATUS
  1649. nicCmCloseCallRecvFIFO (
  1650. IN PVCCB pVc
  1651. )
  1652. // Function Description:
  1653. // This function will do clean up for RecvFifos
  1654. // Includes removing the VC pointer from Pdo Adapter structure.
  1655. // And needs to go through all active remote nodes and free the address ranges on them
  1656. //
  1657. //
  1658. // Arguments
  1659. // PVCCB pVc - The SendFifo that needs to be closed
  1660. //
  1661. // Return Value:
  1662. // Success for now
  1663. //
  1664. {
  1665. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1666. PRECVFIFO_VCCB pRecvFIFOVc = (PRECVFIFO_VCCB)pVc;
  1667. PADDRESS_FIFO pAddressFifo = NULL;
  1668. PSINGLE_LIST_ENTRY pAddressFifoEntry = NULL;
  1669. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1670. TRACE( TL_T, TM_Cm, ( "==> nicCmCloseCallRecvFIFO pVc %x", pVc) );
  1671. NdisStatus = nicFreeAddressRange( pAdapter,
  1672. pRecvFIFOVc->AddressesReturned,
  1673. &pRecvFIFOVc->VcAddressRange,
  1674. &pRecvFIFOVc->hAddressRange );
  1675. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1676. {
  1677. TRACE( TL_I, TM_Cm, ( "Call to Free Address Range Failed pVc at %x",pVc ) );
  1678. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1679. //
  1680. // Do not Break. Continue
  1681. //
  1682. NdisStatus = NDIS_STATUS_SUCCESS;
  1683. }
  1684. pRecvFIFOVc->hAddressRange = NULL;
  1685. pRecvFIFOVc->AddressesReturned = 0;
  1686. pRecvFIFOVc->VcAddressRange.AR_Off_High = 0;
  1687. pRecvFIFOVc->VcAddressRange.AR_Off_Low = 0;
  1688. nicDereferenceCall ((PVCCB)pRecvFIFOVc,
  1689. "nicCmCloseCallRecvFIFO - Free address range" );
  1690. nicFreePacketPool (&pRecvFIFOVc->PacketPool);
  1691. //
  1692. // Free the Slist Entries (AddressFifo, Mdl's) and their associated memory
  1693. // and decrease the refcount for each entry
  1694. //
  1695. nicFreeAllocateAddressRangeSList (pRecvFIFOVc);
  1696. //
  1697. // At this point all the resources of the call have been exhuasted and we can del the pointer in the adapter structure
  1698. //
  1699. VC_ACQUIRE_LOCK (pVc);
  1700. pVc->Hdr.pAF->pAdapter->pRecvFIFOVc = NULL;
  1701. VC_RELEASE_LOCK (pVc);
  1702. //
  1703. // Decrement the Vc Refcount as the adapter no longer has a pointer to it
  1704. //
  1705. nicDereferenceVc (pVc);
  1706. TRACE( TL_T, TM_Cm, ( "<== nicCmCloseCallRecvFIFO Status %x", NdisStatus) );
  1707. return NdisStatus;
  1708. }
  1709. NDIS_STATUS
  1710. nicCmCloseCallSendFIFO (
  1711. IN PVCCB pVc
  1712. )
  1713. // Function Description:
  1714. // This function will do clean up for Send Fifos
  1715. // Includes removing the pointer to the Vc that is in Pdo Adapter structure.
  1716. // For the Send FIFO, the Pdo block is in the pVc->Hdr.pRemoteNode location, so
  1717. // this does not try and find the pRemoteNode
  1718. // Arguments
  1719. // PVCCB pVc - The SendFifo that needs to be closed
  1720. //
  1721. // Return Value:
  1722. // Success for now
  1723. //
  1724. {
  1725. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1726. REMOTE_NODE * pRemoteNode = pVc->Hdr.pRemoteNode;
  1727. PLIST_ENTRY pVcListEntry = NULL;
  1728. PSENDFIFO_VCCB pTempVc = NULL;
  1729. BOOLEAN fVcFound = FALSE;
  1730. TRACE( TL_T, TM_Cm, ( "==> nicCmCloseCallSendFIFO pVc %x", pVc) );
  1731. //
  1732. // SendComplete Handler will complete the close call.
  1733. // This thread should not do it
  1734. // Called in nicFreeSendPacketDataStructures
  1735. //
  1736. //
  1737. // Go through the PdoCb structure and remove the VC from it's VC List
  1738. //
  1739. ASSERT (pRemoteNode != NULL);
  1740. VC_ACQUIRE_LOCK (pVc);
  1741. for (pVcListEntry = pRemoteNode->VcList.Flink;
  1742. pVcListEntry != &pRemoteNode->VcList;
  1743. pVcListEntry = pVcListEntry->Flink)
  1744. {
  1745. pTempVc = (PSENDFIFO_VCCB) CONTAINING_RECORD (pVcListEntry, VCHDR, SinglePdoVcLink);
  1746. //
  1747. // Now remove the Vc from that linked list
  1748. //
  1749. if (pTempVc == (PSENDFIFO_VCCB) pVc )
  1750. {
  1751. nicRemoveEntryList (pVcListEntry);
  1752. TRACE( TL_V, TM_Cm, ( "==> Removed Vc %x From Pdo's Vc List ", pVc) );
  1753. //
  1754. // Remove the reference from the Vc as the Pdo no longer
  1755. // has a pointer to it. This ref was made in MakeCallInitSendFifo
  1756. //
  1757. nicDereferenceCall (pVc, "nicCmCloseCallSendFIFO ");
  1758. NdisStatus = NDIS_STATUS_SUCCESS;
  1759. break;
  1760. }
  1761. }
  1762. //
  1763. // Decerement the Ref on the Pdo as the Vc no longer has a pointer to it.
  1764. // This Ref was made in MakeCallSendFifo function
  1765. //
  1766. nicDereferenceRemoteNode (pRemoteNode, FindRemoteNodeFromAdapter);
  1767. //
  1768. // Null, it so that if we try to access this pointer, we bugcheck
  1769. //
  1770. pVc->Hdr.pRemoteNode = NULL;
  1771. VC_RELEASE_LOCK (pVc);
  1772. //
  1773. // There is no reason why we should not have found the Vc in the Pdo list
  1774. //
  1775. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1776. TRACE( TL_T, TM_Cm, ( "<== nicCmCloseCallSendFIFO Status %x", NdisStatus) );
  1777. NdisStatus = NDIS_STATUS_SUCCESS;
  1778. return NdisStatus;
  1779. }
  1780. NDIS_STATUS
  1781. nicCmCloseCallSendChannel(
  1782. IN PVCCB pVc
  1783. )
  1784. /*++
  1785. Routine Description:
  1786. Free the channel, if its been allocated
  1787. Arguments:
  1788. Return Value:
  1789. --*/
  1790. {
  1791. PADAPTERCB pAdapter = (PADAPTERCB) pVc->Hdr.pAF->pAdapter;
  1792. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
  1793. TRACE( TL_T, TM_Cm, ( "==>nicCmCloseCallSendChannel " ) );
  1794. if (VC_TEST_FLAG (pVc,VCBF_AllocatedChannel) == TRUE)
  1795. {
  1796. nicFreeChannel (pAdapter, pChannelVc->Channel);
  1797. nicDereferenceCall ((PVCCB)pChannelVc, "Close Call - Send Channel - Freeing Channel" );
  1798. }
  1799. TRACE( TL_T, TM_Cm, ( "<==nicCmCloseCallSendChannel " ) );
  1800. return NDIS_STATUS_SUCCESS;
  1801. }
  1802. VOID
  1803. nicChannelCallFreeResources (
  1804. IN PCHANNEL_VCCB pChannelVc,
  1805. IN PADAPTERCB pAdapter,
  1806. IN HANDLE hResource,
  1807. IN ULONG NumDescriptors,
  1808. IN PISOCH_DESCRIPTOR pIsochDescriptor,
  1809. IN BOOLEAN fChannelAllocated,
  1810. IN ULONG Channel,
  1811. IN PNIC_PACKET_POOL pPacketPool
  1812. )
  1813. // Function Description:
  1814. // This function is called from Close call or MakeCall Failure code path.
  1815. // It will detach buffers, free resources, free channel and free bandwdith.
  1816. // It is the responsibility of the caller to do all the appropriate ref counting
  1817. //
  1818. // Arguments
  1819. //
  1820. // pAdapter contains the VDO to which all the IRPs were sent
  1821. // hResource resource handle to be used by the bus driver,
  1822. // NumDescriptors Number of descriptors attached to the buffer,
  1823. // pIsochDesciptor Original pointer to the start of the Buffer Descriptor ,
  1824. // Channel, - Channel that was allocated
  1825. //
  1826. // Return Value:
  1827. // Success if all irps completed succeesfully. Wil be ignored by called
  1828. //
  1829. {
  1830. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1831. STORE_CURRENT_IRQL;
  1832. TRACE( TL_T, TM_Cm, ( "==>nicChannelCallFreeResources " ) );
  1833. TRACE( TL_V, TM_Cm, ( "hResource %x, NumDescriptors %.2x, pIsochDescriptor %x, Channel Allocated %.2x, Channel %x",
  1834. hResource, NumDescriptors, pIsochDescriptor, fChannelAllocated, Channel ) )
  1835. //
  1836. // Reference the pdo structure so it will be around until the end
  1837. // of this function
  1838. // Reference decremented at the end of this function
  1839. //
  1840. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1841. nicReferenceAdapter (pAdapter, "nicChannelCallFreeResources ");
  1842. ADAPTER_RELEASE_LOCK (pAdapter);
  1843. //
  1844. // Do not break out of the loop. We need to try and free as much as possible
  1845. //
  1846. if (pIsochDescriptor != NULL)
  1847. {
  1848. // Detach Buffers
  1849. //
  1850. while (pChannelVc->NumIndicatedIsochDesc != 0 )
  1851. {
  1852. //
  1853. // we will wait for ever, checking periodically for all the packets to return
  1854. //
  1855. TRACE( TL_V, TM_Cm, ( " nicChannelCallFreeResources - Sleeping to wait for packets to be retuerned " ) );
  1856. NdisMSleep ( FIFTY_MILLISECONDS );
  1857. }
  1858. NdisStatus = nicIsochDetachBuffers( pAdapter,
  1859. hResource,
  1860. NumDescriptors,
  1861. pIsochDescriptor );
  1862. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1863. {
  1864. TRACE( TL_A, TM_Cm, ( "nicIsochDetachBuffers FAILED " ) );
  1865. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1866. }
  1867. // First Free Isoch Descriptors and their associated MDLs
  1868. //
  1869. nicFreeIsochDescriptors (NumDescriptors, pIsochDescriptor, (PVCCB)pChannelVc);
  1870. }
  1871. if (hResource != NULL)
  1872. {
  1873. // Free resources
  1874. //
  1875. NdisStatus = nicIsochFreeResources( pAdapter,
  1876. hResource );
  1877. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1878. {
  1879. TRACE( TL_A, TM_Cm, ( "nicIsochFreeResources FAILED " ) );
  1880. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1881. }
  1882. }
  1883. if (fChannelAllocated == TRUE)
  1884. {
  1885. PULONGLONG pLocalHostChannels = &pAdapter->ChannelsAllocatedByLocalHost;
  1886. ASSERT (Channel < NIC1394_MAX_NUMBER_CHANNELS);
  1887. // Free the Channel
  1888. //
  1889. NdisStatus = nicFreeChannel (pAdapter,
  1890. Channel);
  1891. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1892. {
  1893. TRACE( TL_A, TM_Cm, ( "nicIsochFreeChannel FAILED " ) );
  1894. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1895. }
  1896. //
  1897. // Clear the bit in the adapter;s channel bitmap
  1898. //
  1899. VC_ACQUIRE_LOCK (pChannelVc);
  1900. (*pLocalHostChannels)= ((*pLocalHostChannels) & (~(g_ullOne <<Channel)));
  1901. VC_CLEAR_FLAGS( pChannelVc, VCBF_AllocatedChannel);
  1902. VC_RELEASE_LOCK (pChannelVc);
  1903. }
  1904. if (pPacketPool->Handle != NULL)
  1905. {
  1906. nicFreePacketPool(pPacketPool);
  1907. }
  1908. //
  1909. // Remove The Ref that was added in the beginning of the function
  1910. //
  1911. nicDereferenceAdapter (pAdapter, "nicChannelCallFreeResources ");
  1912. MATCH_IRQL;
  1913. TRACE( TL_T, TM_Cm, ( "<==nicChannelCallFreeResources " ) );
  1914. }
  1915. VOID
  1916. nicChannelCallCleanDataStructure (
  1917. IN PCHANNEL_VCCB pChannelVc,
  1918. IN HANDLE hResource,
  1919. IN ULONG NumDescriptors,
  1920. IN PISOCH_DESCRIPTOR pIsochDescriptor,
  1921. IN BOOLEAN fChannelAllocated,
  1922. IN ULONG Channel,
  1923. IN NDIS_HANDLE hPacketPoolHandle,
  1924. OUT PULONG pNumRefsDecremented
  1925. )
  1926. // Function Description:
  1927. // If any of the data fields in the ChannelVc match the
  1928. // corresponding argument in this structure it will be
  1929. // NULLed out and the call dereferenced
  1930. //
  1931. // Called with the lock held.
  1932. //
  1933. // Arguments
  1934. // PCHANNEL_VCCB pChannelVc, - Channel Vc
  1935. // HANDLE hResource, - Handle to resource
  1936. // ULONG NumDescriptors, - Num descriptors will be set to zero
  1937. // PISOCH_DESCRIPTOR pIsochDesciptor, - Pointer to array of isoch descriptors
  1938. // BOOLEAN fChannelAllocated, - Was the Channel allocated
  1939. // ULONG Channel, - channel number
  1940. // NDIS_HANDLE hPacketPoolHandle - Packet pool handle
  1941. //
  1942. //
  1943. //
  1944. // Return Value:
  1945. //
  1946. //
  1947. //
  1948. //
  1949. {
  1950. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1951. ULONG NumRefsDecremented = 0;
  1952. TRACE( TL_T, TM_Cm, ( "==>nicChannelCallCleanDataStructure " ) );
  1953. TRACE( TL_V, TM_Cm, ( "hResource %x, NumDescriptors %.2x, pIsochDescriptor %x, Channel Allocated %.2x, Channel %x",
  1954. hResource, NumDescriptors, pIsochDescriptor, fChannelAllocated, Channel ) )
  1955. if (pChannelVc == NULL)
  1956. {
  1957. return ;
  1958. }
  1959. if ((pChannelVc->NumDescriptors == NumDescriptors )&&
  1960. (pChannelVc->pIsochDescriptor == pIsochDescriptor ) &&
  1961. pIsochDescriptor != NULL )
  1962. {
  1963. pChannelVc->NumDescriptors = 0;
  1964. pChannelVc->pIsochDescriptor = NULL;
  1965. nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure Detach Buffers ");
  1966. NumRefsDecremented ++;
  1967. }
  1968. if (hResource != NULL && pChannelVc->hResource == hResource)
  1969. {
  1970. pChannelVc->hResource = NULL;
  1971. nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure Free Resource ");
  1972. NumRefsDecremented ++;
  1973. }
  1974. if (fChannelAllocated == TRUE)
  1975. {
  1976. ASSERT ( VC_TEST_FLAG (pChannelVc, VCBF_AllocatedChannel) == TRUE);
  1977. VC_CLEAR_FLAGS (pChannelVc, VCBF_AllocatedChannel);
  1978. pChannelVc->Channel = INVALID_CHANNEL;
  1979. nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure - Free Channel");
  1980. NumRefsDecremented ++;
  1981. }
  1982. if (hPacketPoolHandle != NULL && pChannelVc->PacketPool.Handle == hPacketPoolHandle)
  1983. {
  1984. pChannelVc->PacketPool.Handle = NULL;
  1985. nicDereferenceCall ((PVCCB)pChannelVc, "nicChannelCallCleanDataStructure - Packet Pool");
  1986. NumRefsDecremented ++;
  1987. }
  1988. //REMOTE_NODE_RELEASE_LOCK (pRemoteNodePdoCb);
  1989. //
  1990. // Remove The Ref that was added in the beginning of the function
  1991. //
  1992. NdisStatus = NDIS_STATUS_SUCCESS;
  1993. if (pNumRefsDecremented != NULL)
  1994. {
  1995. *pNumRefsDecremented = NumRefsDecremented ;
  1996. }
  1997. TRACE( TL_T, TM_Cm, ( "<==nicChannelCallCleanDataStructure %x", *pNumRefsDecremented ) );
  1998. }
  1999. NDIS_STATUS
  2000. NicCmModifyCallQoS(
  2001. IN NDIS_HANDLE CallMgrVcContext,
  2002. IN PCO_CALL_PARAMETERS CallParameters )
  2003. // Standard 'CmModifyQoSCallHandler' routine called by NDIS when a client
  2004. // requests a modification in the quality of service provided by the
  2005. // virtual circuit. See DDK doc.
  2006. //
  2007. {
  2008. TRACE( TL_T, TM_Cm, ( "NicCmModQoS" ) );
  2009. // There is no useful concept of quality of service for IP media.
  2010. //
  2011. return NDIS_STATUS_NOT_SUPPORTED;
  2012. }
  2013. NDIS_STATUS
  2014. NicCmRequest(
  2015. IN NDIS_HANDLE CallMgrAfContext,
  2016. IN NDIS_HANDLE CallMgrVcContext,
  2017. IN NDIS_HANDLE CallMgrPartyContext,
  2018. IN OUT PNDIS_REQUEST pNdisRequest )
  2019. // Standard 'CmRequestHandler' routine called by NDIS in response to a
  2020. // client's request for information from the call manager.
  2021. //
  2022. {
  2023. AFCB* pAF;
  2024. VCCB* pVc;
  2025. NDIS_STATUS NdisStatus;
  2026. TRACE( TL_T, TM_Cm, ( "==>NicCmReq" ) );
  2027. pAF = (AFCB*) CallMgrAfContext;
  2028. if (pAF->ulTag != MTAG_AFCB )
  2029. {
  2030. ASSERT( !"Atag?" );
  2031. return NDIS_STATUS_INVALID_DATA;
  2032. }
  2033. pVc = (VCCB* )CallMgrVcContext;
  2034. if (pVc && pVc->Hdr.ulTag != MTAG_VCCB)
  2035. {
  2036. ASSERT( !"Vtag?" );
  2037. return NDIS_STATUS_INVALID_DATA;
  2038. }
  2039. #if TODO // Add 1394-specific functionality here.
  2040. #endif
  2041. ASSERT(pNdisRequest != NULL);
  2042. switch (pNdisRequest->RequestType)
  2043. {
  2044. case NdisRequestQueryStatistics:
  2045. case NdisRequestQueryInformation:
  2046. {
  2047. NdisStatus = nicCmQueryInformation(
  2048. CallMgrAfContext,
  2049. CallMgrVcContext,
  2050. CallMgrPartyContext,
  2051. pNdisRequest->DATA.QUERY_INFORMATION.Oid,
  2052. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  2053. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
  2054. &pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
  2055. &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded );
  2056. break;
  2057. }
  2058. case NdisRequestSetInformation:
  2059. {
  2060. NdisStatus = nicCmSetInformation(
  2061. CallMgrAfContext,
  2062. CallMgrVcContext,
  2063. CallMgrPartyContext,
  2064. pNdisRequest->DATA.SET_INFORMATION.Oid,
  2065. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,
  2066. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
  2067. &pNdisRequest->DATA.SET_INFORMATION.BytesRead,
  2068. &pNdisRequest->DATA.SET_INFORMATION.BytesNeeded );
  2069. break;
  2070. }
  2071. default:
  2072. {
  2073. NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
  2074. TRACE( TL_A, TM_Mp, ( "type=%d?", pNdisRequest->RequestType ) );
  2075. break;
  2076. }
  2077. }
  2078. TRACE( TL_T, TM_Cm, ( "<==NicCmReq" ) );
  2079. return NdisStatus;
  2080. }
  2081. VOID
  2082. nicDereferenceAF(
  2083. IN AFCB* pAF )
  2084. // Removes a reference from the address family of adapter control block
  2085. // 'pAdapter', and when frees the block when the last reference is
  2086. // removed.
  2087. //
  2088. {
  2089. LONG lRef;
  2090. lRef = NdisInterlockedDecrement (&pAF->lRef);
  2091. TRACE( TL_T, TM_Ref, ( "DerefAf to %d", lRef ) );
  2092. ASSERT( lRef >= 0 );
  2093. if (lRef == 0)
  2094. {
  2095. ADAPTERCB* pAdapter = pAF->pAdapter;
  2096. // Remove linkages.
  2097. //
  2098. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2099. pAF->pAdapter = NULL;
  2100. nicRemoveEntryList (&pAF->linkAFCB);
  2101. InitializeListHead (&pAF->linkAFCB);
  2102. ADAPTER_RELEASE_LOCK (pAdapter);
  2103. // Tell NDIS it's close is complete.
  2104. //
  2105. ASSERT ( nicReadFlags (&pAF->ulFlags) & ACBF_ClosePending);
  2106. TRACE( TL_I, TM_Cm, ( "NdisMCmCloseAfComp Af %x",pAF ) );
  2107. NdisMCmCloseAddressFamilyComplete(
  2108. NDIS_STATUS_SUCCESS, pAF->NdisAfHandle );
  2109. //
  2110. // Update State information to show that we have called CloseComplete
  2111. //
  2112. nicSetFlags ( &pAF->ulFlags, ACBF_CloseComplete);
  2113. nicClearFlags ( &pAF->ulFlags, ACBF_ClosePending);
  2114. nicDereferenceAdapter (pAdapter, "NdisMCmCloseAfComp "); // nicDereferenceFA (CloseAfComp)
  2115. nicFreeAF (pAF);
  2116. TRACE( TL_I, TM_Cm, ( "NdisMCmCloseAfComp done Af %x", pAF ) );
  2117. }
  2118. }
  2119. BOOLEAN
  2120. nicDereferenceCall(
  2121. IN VCCB* pVc,
  2122. IN PCHAR pDebugPrint
  2123. )
  2124. // Removes a reference from the call active on 'pVc', invoking call clean
  2125. // up when the value reaches zero.
  2126. //
  2127. // CAlled with the lock held
  2128. {
  2129. BOOLEAN bRefZero = FALSE;
  2130. LONG RefCount;
  2131. //
  2132. // If the Ref goes to zero, derefref return true
  2133. //
  2134. bRefZero = nicDereferenceRef (&pVc->Hdr.CallRef, &RefCount);
  2135. TRACE( TL_V, TM_Ref, ( "***DerefCall %x to %d , %s" , pVc, RefCount, pDebugPrint ) );
  2136. if ( bRefZero == TRUE)
  2137. {
  2138. //
  2139. // Dereference the Vc as the Call no longer exists. This reference was
  2140. // added in the beginning of the make call
  2141. nicDereferenceVc (pVc);
  2142. }
  2143. return bRefZero;
  2144. }
  2145. VOID
  2146. nicDereferenceVc(
  2147. IN VCCB* pVc )
  2148. // Removes a reference to the VC control block 'pVc', and when frees the
  2149. // block when the last reference is removed.
  2150. //
  2151. {
  2152. LONG lRef;
  2153. lRef = NdisInterlockedDecrement( &pVc->Hdr.lRef );
  2154. TRACE( TL_V, TM_Ref, ( "DerefVC to %d", lRef ) );
  2155. ASSERT( lRef >= 0 );
  2156. if (lRef == 0 )
  2157. {
  2158. // If close call is pending and the refcount has gone to zero, then call
  2159. //
  2160. ASSERT( pVc->Hdr.ulTag == MTAG_VCCB );
  2161. pVc->Hdr.ulTag = MTAG_FREED;
  2162. FREE_VCCB( pAdapter, pVc );
  2163. TRACE( TL_I, TM_Mp, ( "VCB freed $%p", pVc ) );
  2164. }
  2165. }
  2166. VOID
  2167. nicFreeAF(
  2168. IN AFCB* pAF )
  2169. // Frees all resources allocated for address family 'pAF', including
  2170. // 'pAF' itself.
  2171. //
  2172. {
  2173. #if TODO
  2174. Assert that the various lists (such as pAF->AFVCList) and resources are empty.
  2175. #endif // TODO
  2176. pAF->ulTag = MTAG_FREED;
  2177. FREE_NONPAGED (pAF);
  2178. }
  2179. VOID
  2180. nicReferenceAF(
  2181. IN AFCB* pAF )
  2182. // Adds areference to the address family of adapter block, 'pAdapter'.
  2183. //
  2184. {
  2185. LONG lRef=0;
  2186. lRef = NdisInterlockedIncrement (&pAF->lRef);
  2187. TRACE( TL_V, TM_Ref, ( "RefAf to %d", lRef ) );
  2188. }
  2189. BOOLEAN
  2190. nicReferenceCall(
  2191. IN VCCB* pVc,
  2192. IN PCHAR pDebugPrint
  2193. )
  2194. // Returns true if a reference is added to the active call on VC control
  2195. // block, 'pVc', or false if no reference was added because no call is
  2196. // active.
  2197. //
  2198. {
  2199. BOOLEAN fActive;
  2200. LONG RefNumber;
  2201. fActive = nicReferenceRef (&pVc->Hdr.CallRef, &RefNumber);
  2202. TRACE( TL_V, TM_Ref, ( "***RefCall %x to %d , %s" , pVc, pVc->Hdr.CallRef.ReferenceCount, pDebugPrint ) );
  2203. if ( fActive==FALSE)
  2204. {
  2205. TRACE( TL_N, TM_Ref, ( "RefC Inactive" ) );
  2206. }
  2207. return fActive;
  2208. }
  2209. VOID
  2210. nicReferenceVc(
  2211. IN VCCB* pVc )
  2212. // Adds a reference to the VC control block 'pVc'.
  2213. //
  2214. {
  2215. LONG lRef;
  2216. lRef = NdisInterlockedIncrement (&pVc->Hdr.lRef);
  2217. TRACE( TL_I, TM_Ref, ( "RefVc to %d", lRef ) );
  2218. }
  2219. NDIS_STATUS
  2220. nicAllocateRequestedChannelMakeCallComplete (
  2221. IN PADAPTERCB pAdapter,
  2222. IN PCHANNEL_VCCB pChannelVc,
  2223. IN OUT PULONG pChannel
  2224. )
  2225. // Function Description:
  2226. // This function allocates the channel requested in the make
  2227. // If any channel is requested it will try all 64.
  2228. // If the broadcast channel is requested, it will look for
  2229. // for the channel allocated by the BCM
  2230. // Other wise it will simply try and allocate the requested channel
  2231. //
  2232. // This can be called from the AddFirstRemoteNode code path.
  2233. //
  2234. // Arguments
  2235. // Channel Vc - The channel Vc in question
  2236. // Channel - the channel requested
  2237. //
  2238. // Return Value:
  2239. // Success : if allocate channel succeeds
  2240. // pChannel - contains the allocated channel
  2241. //
  2242. {
  2243. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2244. ULONG Channel = *pChannel;
  2245. BOOLEAN fAnyChannel = FALSE;
  2246. BOOLEAN fFailCall = FALSE;
  2247. TRACE( TL_T, TM_Cm, ( " ==>nicAllocateRequestedChannelMakeCallComplete pAdapter, pVc %x, Channel %x ",
  2248. pAdapter, pChannelVc, *pChannel ) );
  2249. do
  2250. {
  2251. //
  2252. // First make sure we have a good channel number
  2253. //
  2254. if ( (signed long)Channel < (signed long)NIC1394_BROADCAST_CHANNEL ||
  2255. (signed long)Channel >(signed long)MAX_CHANNEL_NUMBER)
  2256. {
  2257. TRACE( TL_A, TM_Cm, ( "Invalid Channel Number, channel %x", Channel) );
  2258. NdisStatus = NDIS_STATUS_INVALID_DATA;
  2259. ASSERT (!(signed long)Channel < (signed long)NIC1394_BROADCAST_CHANNEL ||
  2260. (signed long)Channel >(signed long)MAX_CHANNEL_NUMBER);
  2261. break;
  2262. }
  2263. if ((signed long)Channel == NIC1394_BROADCAST_CHANNEL )
  2264. {
  2265. NETWORK_CHANNELSR* pBCR;
  2266. ULONG i = 0;
  2267. pBCR = &pAdapter->BCRData.IRM_BCR;
  2268. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2269. if (BCR_IS_VALID (pBCR) == FALSE)
  2270. {
  2271. BOOLEAN bWaitSuccessful = FALSE;
  2272. BOOLEAN fIsTheBCRFree = FALSE;
  2273. //
  2274. // BCM algorithm has not completed yet, we need to wait
  2275. //
  2276. TRACE( TL_I, TM_Cm, ( " nicAllocateRequestedChannelMakeCallComplete : BCR Has not completed. About to wait BCR %x ", *pBCR ) );
  2277. BCR_SET_FLAG (pAdapter, BCR_MakeCallPending);
  2278. ADAPTER_RELEASE_LOCK (pAdapter);
  2279. //
  2280. // If we don't have a BCR then we should wait until the BCM algorithm completes
  2281. //
  2282. //
  2283. // Now wait for the BCM algorithm to complete. First we will wait for
  2284. // 5 seconds. (5*1)
  2285. // If we still don't see it, we will reset the bus and hope that the new
  2286. // iteration of BCM will succeed.
  2287. //
  2288. //
  2289. // There can 2 reasons to stop waiting, the BCR is being freed because of a
  2290. // standby or BCR is correct. We check both conditions
  2291. //
  2292. NdisWaitEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent, (5000));
  2293. //
  2294. // We reset the bus - if the BCR is not getting freed and we
  2295. // still do not have a valid BCR . and than we wait
  2296. // for the BCR to complete
  2297. //
  2298. if (BCR_IS_VALID(pBCR) == FALSE &&
  2299. (BCR_TEST_FLAGS (pAdapter, BCR_BCRNeedsToBeFreed | BCR_Freed)== FALSE))
  2300. {
  2301. TRACE( TL_I, TM_Cm, ( " nicAllocateRequestedChannelMakeCallComplete WaitCompleted - About to RESET THE BUS" ) );
  2302. nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
  2303. //
  2304. // Wait for 5 minutes before failing the Make Call
  2305. // (5 minutes is an experimental number)
  2306. //
  2307. {
  2308. BOOLEAN bWait;
  2309. bWait = NdisWaitEvent (
  2310. &pAdapter->BCRData.MakeCallWaitEvent.NdisEvent,
  2311. ONE_MINUTE * 5 );
  2312. }
  2313. }
  2314. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2315. NdisResetEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
  2316. pAdapter->BCRData.MakeCallWaitEvent.EventCode = Nic1394EventCode_InvalidEventCode;
  2317. BCR_CLEAR_FLAG (pAdapter, BCR_MakeCallPending);
  2318. //
  2319. // if we have not got a valid BCR, then fail the call
  2320. //
  2321. if (BCR_IS_VALID(pBCR) == FALSE ||
  2322. BCR_TEST_FLAGS (pAdapter, BCR_BCRNeedsToBeFreed | BCR_Freed))
  2323. {
  2324. fFailCall = TRUE;
  2325. ADAPTER_RELEASE_LOCK(pAdapter);
  2326. NdisStatus = NDIS_STATUS_FAILURE;
  2327. break;
  2328. }
  2329. }
  2330. Channel = pBCR->NC_Channel;
  2331. //
  2332. // Update the VC structure and break .
  2333. // Do not add a reference. Do not set the flag
  2334. //
  2335. pChannelVc->Channel = Channel;
  2336. pChannelVc->Hdr.Nic1394MediaParams.Destination.Channel = Channel;
  2337. //
  2338. // Reference that this Vc now has a pointer in the BCRData. This is dereferneced
  2339. // in the channel close call complete.
  2340. //
  2341. nicReferenceCall ((PVCCB)pChannelVc, "nicAllocateRequestedChannelMakeCallComplete Broadcast VC");
  2342. pAdapter->BCRData.pBroadcastChanneVc = pChannelVc;
  2343. VC_SET_FLAG (pChannelVc, VCBF_BroadcastVc);
  2344. pAdapter->ChannelsAllocatedByLocalHost = pAdapter->ChannelsAllocatedByLocalHost | (g_ullOne<<Channel);
  2345. ADAPTER_RELEASE_LOCK (pAdapter);
  2346. NdisStatus = NDIS_STATUS_SUCCESS;
  2347. break;
  2348. }
  2349. if ((signed long)Channel == NIC1394_ANY_CHANNEL )
  2350. {
  2351. TRACE( TL_V, TM_Cm, ( "Requesting Any Channel %x", Channel) );
  2352. fAnyChannel = TRUE;
  2353. Channel = MAX_CHANNEL_NUMBER;
  2354. }
  2355. //
  2356. // Now begin the request to allocate a channel
  2357. //
  2358. if (fAnyChannel == FALSE)
  2359. {
  2360. TRACE( TL_V, TM_Cm, ( "Requesting Channel %x, on remote node ", Channel ) );
  2361. NdisStatus = nicAllocateChannel ( pAdapter,
  2362. Channel,
  2363. NULL);
  2364. }
  2365. else
  2366. {
  2367. //
  2368. // we need to go through all 64 channels.
  2369. //
  2370. do
  2371. {
  2372. NdisStatus = nicAllocateChannel ( pAdapter,
  2373. Channel,
  2374. NULL);
  2375. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2376. {
  2377. if (Channel == 0 )
  2378. {
  2379. //
  2380. // We now need to fail the make call as the user asked for any channel
  2381. // and none are available
  2382. //
  2383. break;
  2384. }
  2385. Channel --;
  2386. }
  2387. else
  2388. {
  2389. //
  2390. // We succeeded in allocating a channel .. break
  2391. //
  2392. break;
  2393. }
  2394. } while (TRUE);
  2395. }
  2396. //
  2397. // Status of Channel allocation. If AnyChannel == TRUE then we need to make sure that
  2398. // a channel was allocated
  2399. //
  2400. if (NdisStatus == NDIS_STATUS_SUCCESS)
  2401. {
  2402. VC_ACQUIRE_LOCK (pChannelVc);
  2403. VC_SET_FLAG( pChannelVc, VCBF_AllocatedChannel);
  2404. pChannelVc->Channel = Channel;
  2405. pChannelVc->Hdr.Nic1394MediaParams.Destination.Channel = Channel;
  2406. //
  2407. // Record the channel number in the adpater structure
  2408. //
  2409. pAdapter->ChannelsAllocatedByLocalHost = pAdapter->ChannelsAllocatedByLocalHost | (g_ullOne<<Channel);
  2410. VC_RELEASE_LOCK (pChannelVc);
  2411. nicReferenceCall ((PVCCB)pChannelVc, "nicAllocateRequestedChannelMakeCallComplete -Allocated Channel");
  2412. }
  2413. else
  2414. {
  2415. //
  2416. // we failed to allocate any channel and are going to fail
  2417. //
  2418. if (fAnyChannel == TRUE)
  2419. {
  2420. Channel = 0xff;
  2421. NdisStatus = NDIS_STATUS_RESOURCES;
  2422. break;
  2423. }
  2424. else
  2425. {
  2426. //
  2427. // If the Call specifically wants the channel to
  2428. // be allocated, we return the correct channel allocate
  2429. // status to it,
  2430. //
  2431. // Otherwise we overwrite and presume that another node may
  2432. // already have allocated the channel
  2433. //
  2434. if (VC_TEST_FLAG (pChannelVc,VCBF_NeedsToAllocateChannel) == FALSE)
  2435. {
  2436. NdisStatus = NDIS_STATUS_SUCCESS;
  2437. }
  2438. else
  2439. {
  2440. ASSERT (!"Failing make call because channel was allocated, Hit 'g'");
  2441. }
  2442. }
  2443. }
  2444. } while (FALSE);
  2445. *pChannel = Channel;
  2446. TRACE( TL_T, TM_Cm, ( "<==nicAllocateRequestedChannelMakeCallComplete Status %x Channel %x", NdisStatus, *pChannel ) );
  2447. return NdisStatus;
  2448. }
  2449. NDIS_STATUS
  2450. nicFindRemoteNodeFromAdapter(
  2451. IN PADAPTERCB pAdapter,
  2452. IN PDEVICE_OBJECT pRemotePdo,
  2453. IN UINT64 UniqueId,
  2454. IN OUT REMOTE_NODE ** ppRemoteNode
  2455. )
  2456. /*++
  2457. Routine Description:
  2458. This routine matches either a Remote Node' pdo OR unique
  2459. Id to the Remote node's on the adapter
  2460. It walks the RemoteNode List in the Adapter Structure
  2461. and tries to find a match for the Unique Id,
  2462. or match the remote Pdo from the adapter's PdoList
  2463. Arguments:
  2464. pAdapter - pAdapter on which to search
  2465. pRemoptePdo - Remote Pdo to find
  2466. UniqueId - Unique Id to find
  2467. ppRemoteNode - Remote Node structure
  2468. Return Value:
  2469. Success if the node is found
  2470. --*/
  2471. {
  2472. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2473. PLIST_ENTRY pPdoListEntry = NULL;
  2474. PREMOTE_NODE pRemoteNode = NULL;
  2475. BOOLEAN fPdoFound = FALSE;
  2476. STORE_CURRENT_IRQL;
  2477. TRACE( TL_T, TM_Cm, ( "==>nicFindRemoteNodeFromAdapter pAdapter is %x, ,Pdo %x, UniqueId %I64x ", pAdapter, pRemotePdo, UniqueId ) );
  2478. //
  2479. // Validate the parameters
  2480. //
  2481. ASSERT (pAdapter != NULL);
  2482. TRACE( TL_I, TM_Cm, ( " Request to Match UniqueID %I64x or pRemotePdo %x", UniqueId, pRemotePdo) );
  2483. do
  2484. {
  2485. (*ppRemoteNode) = NULL;
  2486. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2487. //
  2488. // Check for empty list
  2489. //
  2490. if (pAdapter->PDOList.Flink == &pAdapter->PDOList)
  2491. {
  2492. ADAPTER_RELEASE_LOCK (pAdapter);
  2493. MATCH_IRQL;
  2494. NdisStatus = NDIS_STATUS_FAILURE;
  2495. (*ppRemoteNode) = NULL;
  2496. TRACE( TL_A, TM_Cm, ( " NO REMOTE NODES PRESENT FAILING MAKE CALL ") );
  2497. break;
  2498. }
  2499. //
  2500. // go through all the Pdo's on the adapter
  2501. //
  2502. for (pPdoListEntry = pAdapter->PDOList.Flink;
  2503. pPdoListEntry!= &pAdapter->PDOList;
  2504. pPdoListEntry = pPdoListEntry->Flink)
  2505. {
  2506. pRemoteNode = CONTAINING_RECORD( pPdoListEntry,
  2507. REMOTE_NODE,
  2508. linkPdo);
  2509. //
  2510. // Check for the two cases, i.e unique Id's match or Pdo's match
  2511. //
  2512. if ( pRemoteNode->UniqueId == UniqueId || pRemoteNode->pPdo == pRemotePdo)
  2513. {
  2514. TRACE( TL_I, TM_Cm, ( " Matched UniqueID or pRemotePdo for Pdo%x",pRemoteNode->pPdo) );
  2515. *ppRemoteNode = pRemoteNode;
  2516. nicReferenceRemoteNode (pRemoteNode, FindRemoteNodeFromAdapter);
  2517. //
  2518. // We ref pRemoteNode to keep it alive once we release the lock.
  2519. // Caller is responsible for derefing pRemoteNode.
  2520. //
  2521. fPdoFound = TRUE;
  2522. NdisStatus = NDIS_STATUS_SUCCESS;
  2523. break;
  2524. }
  2525. else
  2526. {
  2527. TRACE( TL_A, TM_Cm, ( "remote node's Unique ID's %I64x, given UniqueID %I64x ", pRemoteNode->UniqueId, UniqueId ) );
  2528. }
  2529. }
  2530. ADAPTER_RELEASE_LOCK (pAdapter);
  2531. MATCH_IRQL;
  2532. TRACE( TL_V, TM_Cm, ( "Is PdoFound %.2x, RemoteNode at %x ", fPdoFound, &fPdoFound ) );
  2533. if (fPdoFound ==FALSE)
  2534. {
  2535. TRACE( TL_A, TM_Cm, ( "Remote Node was NOT Found: Make Call failed " ) );
  2536. ASSERT ((*ppRemoteNode) == NULL);
  2537. }
  2538. } while (FALSE);
  2539. TRACE( TL_T, TM_Cm, ( "<==nicFindRemoteNodeFromAdapter pPdoBlock %x",(*ppRemoteNode) ) );
  2540. MATCH_IRQL;
  2541. return NdisStatus;
  2542. }
  2543. NDIS_STATUS
  2544. nicCmQueryInformation(
  2545. IN NDIS_HANDLE CallMgrAfContext,
  2546. IN NDIS_HANDLE CallMgrVcContext,
  2547. IN NDIS_HANDLE CallMgrPartyContext,
  2548. IN NDIS_OID Oid,
  2549. IN PVOID InformationBuffer,
  2550. IN ULONG InformationBufferLength,
  2551. OUT PULONG BytesWritten,
  2552. OUT PULONG BytesNeeded
  2553. )
  2554. // Handle QueryInformation requests. Arguments are as for the standard
  2555. // NDIS 'CallMgrQueryInformation' handler except this routine does not
  2556. // count on being serialized with respect to other requests.
  2557. //
  2558. {
  2559. NDIS_STATUS NdisStatus;
  2560. ULONG ulInfo;
  2561. VOID* pInfo;
  2562. ULONG ulInfoLen;
  2563. USHORT usInfo;
  2564. // The next variables are used to setup the data structures that are
  2565. // used to respond to the OIDs they correspond to
  2566. //
  2567. NDIS_CO_LINK_SPEED CoLinkSpeed;
  2568. NIC1394_LOCAL_NODE_INFO LocalNodeInfo;
  2569. NIC1394_VC_INFO VcInfo;
  2570. PVCCB pVc;
  2571. TRACE( TL_T, TM_Cm, ( "==>nicCmQueryInformation %x, Vc %x", Oid, CallMgrVcContext ) );
  2572. // The cases in this switch statement find or create a buffer containing
  2573. // the requested information and point 'pInfo' at it, noting it's length
  2574. // in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
  2575. // buffer is set up as the default.
  2576. //
  2577. ulInfo = 0;
  2578. pInfo = &ulInfo;
  2579. ulInfoLen = sizeof (ulInfo);
  2580. NdisStatus = NDIS_STATUS_SUCCESS;
  2581. // Validate the arguments
  2582. //
  2583. pVc = (VCCB* )CallMgrVcContext;
  2584. if (pVc && pVc->Hdr.ulTag != MTAG_VCCB)
  2585. {
  2586. ASSERT( !"Vtag?" );
  2587. return NDIS_STATUS_INVALID_DATA;
  2588. }
  2589. // Perform the request
  2590. //
  2591. switch (Oid)
  2592. {
  2593. case OID_1394_VC_INFO:
  2594. {
  2595. // Returns information about the VC that is being queried
  2596. //
  2597. TRACE( TL_N, TM_Mp, ("QInfo(OID_1394_VC_INFO)") );
  2598. VcInfo.Destination = pVc->Hdr.Nic1394MediaParams.Destination;
  2599. pInfo = &VcInfo;
  2600. ulInfoLen = sizeof (VcInfo);
  2601. break;
  2602. }
  2603. case OID_1394_ISSUE_BUS_RESET:
  2604. {
  2605. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  2606. TRACE( TL_V, TM_Mp, ( " OID_1394_ISSUE_BUS_RESET" ) );
  2607. if (InformationBufferLength == sizeof(ULONG))
  2608. {
  2609. nicIssueBusReset (pAdapter, (*(PULONG)InformationBuffer));
  2610. }
  2611. else
  2612. {
  2613. nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
  2614. }
  2615. break;
  2616. }
  2617. default:
  2618. {
  2619. TRACE( TL_A, TM_Cm, ( "Q-OID=$%08x?", Oid ) );
  2620. NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
  2621. ulInfoLen = 0;
  2622. break;
  2623. }
  2624. }
  2625. if (ulInfoLen > InformationBufferLength)
  2626. {
  2627. // Caller's buffer is too small. Tell him what he needs.
  2628. //
  2629. *BytesNeeded = ulInfoLen;
  2630. *BytesWritten = 0;
  2631. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  2632. }
  2633. else
  2634. {
  2635. // Copy the found result to caller's buffer.
  2636. //
  2637. if (ulInfoLen > 0)
  2638. {
  2639. NdisMoveMemory (InformationBuffer, pInfo, ulInfoLen );
  2640. DUMPDW( TL_N, TM_Mp, pInfo, ulInfoLen );
  2641. }
  2642. *BytesNeeded = *BytesWritten = ulInfoLen;
  2643. }
  2644. TRACE( TL_T, TM_Cm, ( "<==nicCmQueryInformation %x",NdisStatus ) );
  2645. return NdisStatus;
  2646. }
  2647. NDIS_STATUS
  2648. nicCmSetInformation(
  2649. IN NDIS_HANDLE CallMgrAfContext,
  2650. IN NDIS_HANDLE CallMgrVcContext,
  2651. IN NDIS_HANDLE CallMgrPartyContext,
  2652. IN NDIS_OID Oid,
  2653. IN PVOID InformationBuffer,
  2654. IN ULONG InformationBufferLength,
  2655. OUT PULONG BytesRead,
  2656. OUT PULONG BytesNeeded
  2657. )
  2658. //
  2659. // Not implemented yet. Will be used to set information
  2660. //
  2661. {
  2662. NDIS_STATUS NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
  2663. PVCCB pVc;
  2664. TRACE( TL_T, TM_Cm, ( "==>NicCmMakeCallInitVc Oid %x",Oid ) );
  2665. // Validate the arguments
  2666. //
  2667. UNREFERENCED_PARAMETER(CallMgrAfContext);
  2668. UNREFERENCED_PARAMETER(CallMgrVcContext);
  2669. UNREFERENCED_PARAMETER(CallMgrAfContext);
  2670. UNREFERENCED_PARAMETER(CallMgrPartyContext);
  2671. UNREFERENCED_PARAMETER(Oid);
  2672. UNREFERENCED_PARAMETER(InformationBuffer);
  2673. UNREFERENCED_PARAMETER(InformationBufferLength);
  2674. UNREFERENCED_PARAMETER(BytesRead);
  2675. UNREFERENCED_PARAMETER(BytesNeeded);
  2676. TRACE( TL_T, TM_Cm, ( "<==NicCmMakeCallInitVc %x",NdisStatus ) );
  2677. return NDIS_STATUS_FAILURE;
  2678. }
  2679. NDIS_STATUS
  2680. nicInitRecvFifoDataStructures (
  2681. IN PRECVFIFO_VCCB pRecvFIFOVc
  2682. )
  2683. // Function Description:
  2684. // This function will initialize the data structures, buffers etc that are needed on
  2685. // all the allocate address range Irps that will be called because of the RecvFifo Vc
  2686. //
  2687. // Arguments
  2688. // pRecvFIFOVc - RecvFifo Vc structure
  2689. //
  2690. // Return Value:
  2691. // SUCCESS: If all the values are initiaized successfully
  2692. // Appropriate error code otherwise
  2693. {
  2694. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2695. NDIS_HANDLE PacketPoolHandle = NULL;
  2696. PSLIST_HEADER pSlistHead = NULL;
  2697. extern UINT NumRecvFifos ;
  2698. UINT AllocateNumBuffers = NumRecvFifos;
  2699. NIC_PACKET_POOL PacketPool;
  2700. TRACE( TL_T, TM_Cm, ( "==> nicInitRecvFifoDataStructures pVc %x",pRecvFIFOVc ) );
  2701. do
  2702. {
  2703. PacketPool.Handle = NULL;
  2704. //
  2705. // Initialize the PacketPool
  2706. //
  2707. NdisAllocatePacketPoolEx ( &NdisStatus,
  2708. &PacketPool.Handle,
  2709. MIN_PACKET_POOL_SIZE,
  2710. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  2711. sizeof (RSVD) );
  2712. if (NdisStatus!= NDIS_STATUS_SUCCESS)
  2713. {
  2714. ASSERT(NdisStatus != NDIS_STATUS_SUCCESS);
  2715. pRecvFIFOVc->PacketPool.Handle = NULL;
  2716. break;
  2717. }
  2718. //
  2719. // Do not acquire the lock as we cannot have two make
  2720. // calls for the same Vc at the same time
  2721. //
  2722. //
  2723. // Create an S-list and intialize its structures
  2724. //
  2725. ExInitializeSListHead (&pRecvFIFOVc->FifoSListHead);
  2726. KeInitializeSpinLock (&pRecvFIFOVc->FifoSListSpinLock);
  2727. pRecvFIFOVc->Hdr.MTU = pRecvFIFOVc->Hdr.Nic1394MediaParams.MTU ;
  2728. TRACE( TL_I, TM_Cm, ( " Recv FIFO MTU is %d ", pRecvFIFOVc->Hdr.MTU ) );
  2729. ASSERT (pRecvFIFOVc->Hdr.MTU >= 512);
  2730. //
  2731. // Now, fill the Slist with buffers.
  2732. //
  2733. NdisStatus = nicFillAllocateAddressRangeSList (pRecvFIFOVc, &AllocateNumBuffers);
  2734. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2735. {
  2736. //
  2737. // nicFillAllocateAddressRangeSlist does its own clean up
  2738. // but we should free the Packet Pool Allocated above
  2739. //
  2740. if (PacketPool.Handle != NULL)
  2741. {
  2742. nicFreePacketPool (&PacketPool);
  2743. }
  2744. break;
  2745. }
  2746. ASSERT(AllocateNumBuffers == NumRecvFifos );
  2747. pRecvFIFOVc->PacketPool= PacketPool;
  2748. pRecvFIFOVc->PacketPool.AllocatedPackets = 0;
  2749. pRecvFIFOVc->NumAllocatedFifos = AllocateNumBuffers ;
  2750. TRACE( TL_V, TM_Cm, ( "PacketPool allocated at %x", PacketPool.Handle) );
  2751. } while (FALSE);
  2752. TRACE( TL_T, TM_Cm, ( "<== nicInitRecvFifoDataStructures Status %x", NdisStatus ) );
  2753. return NdisStatus;
  2754. }
  2755. VOID
  2756. nicUnInitRecvFifoDataStructures (
  2757. IN PRECVFIFO_VCCB pRecvFIFOVc
  2758. )
  2759. /*++
  2760. Routine Description:
  2761. Frees all the resources that were allocated in nicInitRecvFifoDataStructures
  2762. Arguments:
  2763. Return Value:
  2764. --*/
  2765. {
  2766. if (pRecvFIFOVc->PacketPool.Handle != NULL)
  2767. {
  2768. ASSERT (pRecvFIFOVc->PacketPool.AllocatedPackets == 0);
  2769. nicFreePacketPool (&pRecvFIFOVc->PacketPool);
  2770. }
  2771. pRecvFIFOVc->PacketPool.Handle = NULL;
  2772. if (pRecvFIFOVc->FifoSListHead.Alignment != 0)
  2773. {
  2774. nicFreeAllocateAddressRangeSList(pRecvFIFOVc);
  2775. ASSERT (pRecvFIFOVc->FifoSListHead.Alignment == 0)
  2776. }
  2777. pRecvFIFOVc->FifoSListHead.Alignment = 0;
  2778. }
  2779. ULONG
  2780. nicGetMaxPayLoadForSpeed(
  2781. IN ULONG Speed,
  2782. IN ULONG mtu
  2783. )
  2784. // Function Description:
  2785. // The purpose is to map a speed to the max payload that
  2786. // can be delivered at that speed . this is limited by the Bytes PerFrameAvailable
  2787. //
  2788. // Arguments
  2789. // Speed - the speed supported by the Bus driver or the Max speed between devices
  2790. // BytesPerFrameAvailable Bytes per frame available on the bus.
  2791. //
  2792. //
  2793. // Return Value:
  2794. // Minimin of the Size determined by the payload and the size determined by the
  2795. // byte per frame available.
  2796. {
  2797. ULONG maxIsochPayload = ISOCH_PAYLOAD_400_RATE;
  2798. TRACE( TL_T, TM_Cm, ( "<==nicGetMaxPayLoadForSpeed %x", Speed ) );
  2799. switch (Speed)
  2800. {
  2801. case SPEED_FLAGS_100:
  2802. maxIsochPayload = ISOCH_PAYLOAD_100_RATE;
  2803. break;
  2804. case SPEED_FLAGS_200:
  2805. maxIsochPayload = ISOCH_PAYLOAD_200_RATE;
  2806. break;
  2807. case SPEED_FLAGS_400:
  2808. maxIsochPayload = ISOCH_PAYLOAD_400_RATE;
  2809. break;
  2810. case SPEED_FLAGS_800:
  2811. maxIsochPayload = ISOCH_PAYLOAD_800_RATE;
  2812. break;
  2813. case SPEED_FLAGS_1600:
  2814. maxIsochPayload = ISOCH_PAYLOAD_1600_RATE;
  2815. break;
  2816. default :
  2817. TRACE( TL_A, TM_Cm, ( "Invalid Speed %x", Speed ) );
  2818. ASSERT (Speed < SPEED_FLAGS_1600);
  2819. maxIsochPayload = ISOCH_PAYLOAD_1600_RATE;
  2820. break;
  2821. }
  2822. if (maxIsochPayload > mtu)
  2823. {
  2824. maxIsochPayload = mtu;
  2825. }
  2826. TRACE( TL_T, TM_Cm, ( "<==nicGetMaxPayLoadForSpeed, payload %x", maxIsochPayload ) );
  2827. return maxIsochPayload;
  2828. }
  2829. //---------------------------------------------------------------------------------
  2830. // SAP function - all of them return failure
  2831. //-------------------------------------------------------------------------------
  2832. NDIS_STATUS
  2833. nicRegisterSapHandler(
  2834. IN NDIS_HANDLE CallMgrAfContext,
  2835. IN PCO_SAP Sap,
  2836. IN NDIS_HANDLE NdisSapHandle,
  2837. OUT PNDIS_HANDLE CallMgrSapContext
  2838. )
  2839. {
  2840. *CallMgrSapContext = NULL;
  2841. return NDIS_STATUS_FAILURE;
  2842. }
  2843. NDIS_STATUS
  2844. nicDeregisterSapHandler(
  2845. IN NDIS_HANDLE CallMgrSapContext
  2846. )
  2847. {
  2848. return NDIS_STATUS_FAILURE;
  2849. }
  2850. NDIS_STATUS
  2851. nicCmDropPartyHandler(
  2852. IN NDIS_HANDLE CallMgrPartyContext,
  2853. IN PVOID CloseData OPTIONAL,
  2854. IN UINT Size OPTIONAL
  2855. )
  2856. {
  2857. return NDIS_STATUS_FAILURE;
  2858. }
  2859. NDIS_STATUS
  2860. nicCmAddPartyHandler(
  2861. IN NDIS_HANDLE CallMgrVcContext,
  2862. IN OUT PCO_CALL_PARAMETERS CallParameters,
  2863. IN NDIS_HANDLE NdisPartyHandle,
  2864. OUT PNDIS_HANDLE CallMgrPartyContext
  2865. )
  2866. {
  2867. *CallMgrPartyContext = NULL;
  2868. return NDIS_STATUS_FAILURE;
  2869. }
  2870. NDIS_STATUS
  2871. nicAllocateChannelResourcesAndListen (
  2872. IN PADAPTERCB pAdapter,
  2873. IN PCHANNEL_VCCB pChannelVc
  2874. )
  2875. // Function Description:
  2876. // This function isolated the reource and channel allocation portion
  2877. // of initializing a MakeCall. This lets us do the same work when the
  2878. // AddRemoteNode code path is hit and there is an existing Channel Vc
  2879. //
  2880. // Arguments
  2881. // pChannelVc, This is the send fifo that needs to be initilaized
  2882. //
  2883. // Return Value:
  2884. //
  2885. // Success if the irps sent to the driver succeed
  2886. //
  2887. //
  2888. {
  2889. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2890. PDEVICE_OBJECT ArrayRemotePDO[NIC1394_MAX_NUMBER_NODES];
  2891. ULONG Channel = INVALID_CHANNEL;
  2892. ULONG Speed;
  2893. PNIC1394_MEDIA_PARAMETERS pN1394Params;
  2894. ULONG NumDescriptors = MAX_NUM_ISOCH_DESCRIPTOR;
  2895. PISOCH_DESCRIPTOR pIsochDescriptor = NULL;
  2896. ULONG MaxBufferSize;
  2897. ULONG MaxBytesPerFrame;
  2898. HANDLE hResource;
  2899. CYCLE_TIME CycleTime;
  2900. ULARGE_INTEGER uliChannelMap;
  2901. ULONG ResourceFlags = 0;
  2902. ULONG State = 0;
  2903. BOOLEAN fBroadcastVc = FALSE;
  2904. BOOLEAN fChannelAllocate = FALSE;
  2905. BOOLEAN fIsMultiChannel = FALSE;
  2906. enum
  2907. {
  2908. StartState,
  2909. AllocatedResources,
  2910. AllocatedBuffers,
  2911. AttachedBuffers,
  2912. IsochListen
  2913. };
  2914. STORE_CURRENT_IRQL;
  2915. TRACE( TL_T, TM_Cm, ( "==> nicAllocateChannelResourcesAndListen pAdapter %x, pChannelVc %x ",
  2916. pAdapter,pChannelVc ) );
  2917. State = StartState;
  2918. pN1394Params = (PNIC1394_MEDIA_PARAMETERS)&pChannelVc->Hdr.Nic1394MediaParams;
  2919. //
  2920. // Use the original request to figure out which channel needs to be allocated
  2921. //
  2922. fIsMultiChannel = (pN1394Params->Destination.AddressType == NIC1394AddressType_MultiChannel);
  2923. if (fIsMultiChannel == FALSE)
  2924. {
  2925. Channel = pN1394Params->Destination.Channel;
  2926. }
  2927. do
  2928. {
  2929. if (pAdapter == NULL)
  2930. {
  2931. BREAK (TM_Cm, ("nicAllocateChannelResourcesAndListen : pAdapter == NULL ") );
  2932. }
  2933. //
  2934. // Get the max payload that is possible for isoch receives
  2935. //
  2936. if (pAdapter->Speed == 0)
  2937. {
  2938. nicUpdateLocalHostSpeed (pAdapter);
  2939. }
  2940. Speed = pAdapter->Speed;
  2941. switch (Speed)
  2942. {
  2943. case SPEED_FLAGS_100 :
  2944. {
  2945. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_100_RATE;
  2946. break;
  2947. }
  2948. case SPEED_FLAGS_200 :
  2949. {
  2950. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_200_RATE ;
  2951. break;
  2952. }
  2953. case SPEED_FLAGS_400 :
  2954. {
  2955. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  2956. break;
  2957. }
  2958. case SPEED_FLAGS_800 :
  2959. {
  2960. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  2961. break;
  2962. }
  2963. case SPEED_FLAGS_1600 :
  2964. {
  2965. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  2966. break;
  2967. }
  2968. case SPEED_FLAGS_3200 :
  2969. {
  2970. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  2971. break;
  2972. }
  2973. default :
  2974. {
  2975. ASSERT (Speed <= SPEED_FLAGS_3200 && Speed != 0 );
  2976. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_400_RATE;
  2977. break;
  2978. }
  2979. }
  2980. //
  2981. // If the make call wants the channel to allocate we try and allocate the channel,
  2982. // In the Multichannel case, we do not allocate the channel (as this is
  2983. // for listening purposes only )
  2984. //
  2985. fBroadcastVc = (Channel == NIC1394_BROADCAST_CHANNEL);
  2986. fChannelAllocate = VC_TEST_FLAG (pChannelVc,VCBF_NeedsToAllocateChannel);
  2987. if (fChannelAllocate || fBroadcastVc )
  2988. {
  2989. ASSERT (pChannelVc->Hdr.VcType != NIC1394_MultiChannel);
  2990. NdisStatus = nicAllocateRequestedChannelMakeCallComplete( pAdapter,
  2991. pChannelVc,
  2992. &Channel );
  2993. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2994. {
  2995. BREAK( TM_Cm, ( " nicAllocateChannelResourcesAndListen : nicAllocateRequestedChannelMakeCallComplete FAILED") );
  2996. }
  2997. TRACE( TL_I, TM_Cm, ( "Using Channel %x, on remote node ", Channel ) );
  2998. ASSERT (Channel < NIC1394_MAX_NUMBER_NODES);
  2999. ResourceFlags = 0;
  3000. uliChannelMap.QuadPart = 0;
  3001. }
  3002. else
  3003. {
  3004. //
  3005. // Multichannels - no allocation just update the ullChannelMap
  3006. //
  3007. uliChannelMap = pChannelVc->uliChannelMap;
  3008. if (fIsMultiChannel == TRUE)
  3009. {
  3010. ResourceFlags = RESOURCE_USE_MULTICHANNEL;
  3011. }
  3012. else
  3013. {
  3014. pChannelVc->Channel = Channel ;
  3015. }
  3016. }
  3017. MaxBufferSize = min(pN1394Params->MTU + sizeof(GASP_HEADER) , pChannelVc->Hdr.MaxPayload);
  3018. MaxBytesPerFrame = MaxBufferSize;
  3019. TRACE( TL_V, TM_Cm, ( " MAxBufferSize %x, MaxBytesPerFrame %x", MaxBufferSize, MaxBytesPerFrame ) );
  3020. //
  3021. // Add the flags used for resources allocation
  3022. //
  3023. ResourceFlags |= (RESOURCE_USED_IN_LISTENING | RESOURCE_USE_PACKET_BASED | RESOURCE_BUFFERS_CIRCULAR);
  3024. //
  3025. // MaxBufferSize should be an integral mutiple of MaxBytesPerFram
  3026. //
  3027. ASSERT (MaxBufferSize % MaxBytesPerFrame == 0);
  3028. //
  3029. // Noe allocate the resource
  3030. //
  3031. NdisStatus = nicIsochAllocateResources( pAdapter,
  3032. Speed,
  3033. ResourceFlags,
  3034. Channel,
  3035. MaxBytesPerFrame,
  3036. NumDescriptors,
  3037. MaxBufferSize,
  3038. 0, //QuadletsToStrip,
  3039. uliChannelMap,
  3040. &hResource);
  3041. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3042. {
  3043. hResource = NULL;
  3044. BREAK(TM_Cm, ( "Allocate Resources Failed. Make Call failed ") );
  3045. }
  3046. State = AllocatedResources;
  3047. ASSERT (NumDescriptors != 0);
  3048. ASSERT (pChannelVc->Hdr.MTU != 0);
  3049. //
  3050. // Get Isoch Descriptors that will be submitted to the Bus drivers
  3051. //
  3052. //
  3053. // Add room for the Isoch Header and Isoch prefix
  3054. //
  3055. MaxBufferSize += ISOCH_PREFIX_LENGTH ;
  3056. NdisStatus = nicAllocateAndInitializeIsochDescriptors (pChannelVc,
  3057. NumDescriptors,
  3058. MaxBufferSize,
  3059. &pIsochDescriptor );
  3060. if(NdisStatus != NDIS_STATUS_SUCCESS)
  3061. {
  3062. BREAK (TM_Cm, (" nicAllocateAndInitializeIsochDescriptors failed, Make Call Failed") );
  3063. }
  3064. ASSERT (pIsochDescriptor != NULL);
  3065. State = AllocatedBuffers;
  3066. NdisStatus = nicIsochAttachBuffers( pAdapter,
  3067. hResource,
  3068. NumDescriptors,
  3069. pIsochDescriptor);
  3070. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3071. {
  3072. BREAK (TM_Cm, "nicIsochAttachBuffers FAILED");
  3073. }
  3074. State = AttachedBuffers;
  3075. //
  3076. // Start the Listen
  3077. //
  3078. NdisZeroMemory (&CycleTime, sizeof(CycleTime));
  3079. NdisStatus = nicIsochListen (pAdapter,
  3080. hResource,
  3081. 0,
  3082. CycleTime ); // Cycle Time is Zero
  3083. //
  3084. // Update the Vc structure, because we have now succeeded
  3085. //
  3086. State = IsochListen;
  3087. VC_ACQUIRE_LOCK (pChannelVc);
  3088. //
  3089. // If broadcast channel, then decrease the speed setting, and fragment
  3090. //
  3091. if (Channel == NIC1394_BROADCAST_CHANNEL)
  3092. {
  3093. Speed = SPEED_FLAGS_200 ;
  3094. pChannelVc->Hdr.MaxPayload = ISOCH_PAYLOAD_200_RATE ;
  3095. }
  3096. pChannelVc->Channel = Channel;
  3097. pChannelVc->MaxBufferSize = MaxBufferSize - ISOCH_PREFIX_LENGTH;
  3098. pChannelVc->Speed = Speed;
  3099. pChannelVc->hResource = hResource;
  3100. //
  3101. // Reference Call for allocated resource handle
  3102. //
  3103. nicReferenceCall ( (PVCCB) pChannelVc, "nicAllocateRequestedChannelMakeCallComplete - allocate resources ");
  3104. pChannelVc->NumDescriptors = NumDescriptors;
  3105. pChannelVc->pIsochDescriptor = pIsochDescriptor;
  3106. //
  3107. // Reference the call because we will now need to detach buffers
  3108. //
  3109. nicReferenceCall ( (PVCCB) pChannelVc, "nicAllocateRequestedChannelMakeCallComplete - Attach Buffers");
  3110. //
  3111. // We have succeded in allocating all resources.
  3112. // If the Freed Resources flag is set it needs to be cleared
  3113. //
  3114. VC_CLEAR_FLAGS (pChannelVc, VCBF_FreedResources);
  3115. VC_RELEASE_LOCK (pChannelVc);
  3116. //
  3117. // No more failures
  3118. //
  3119. } while (FALSE);
  3120. //
  3121. // Time to do clean up based on what resources were allocated.
  3122. // There are no failures after the point where the refs for
  3123. // Allocate Resources and Attach Buffers are added, so
  3124. // No Derefs in the following code except in ( FreeIsochDesc)
  3125. //
  3126. if (NdisStatus != NDIS_STATUS_SUCCESS )
  3127. {
  3128. BOOLEAN fAllocatedChannel = FALSE;
  3129. switch (State)
  3130. {
  3131. case IsochListen:
  3132. {
  3133. nicIsochStop(pAdapter, hResource);
  3134. FALL_THROUGH
  3135. }
  3136. case AttachedBuffers:
  3137. {
  3138. nicIsochDetachBuffers( pAdapter,
  3139. hResource,
  3140. NumDescriptors,
  3141. pIsochDescriptor );
  3142. FALL_THROUGH;
  3143. }
  3144. case AllocatedBuffers:
  3145. {
  3146. //
  3147. // Free the isoch Buffers and Descriptors that were
  3148. // allocated
  3149. //
  3150. nicFreeIsochDescriptors(NumDescriptors,
  3151. pIsochDescriptor,
  3152. (PVCCB) pChannelVc);
  3153. FALL_THROUGH
  3154. }
  3155. case AllocatedResources:
  3156. {
  3157. //
  3158. // Free the Isoch Resources Handle
  3159. //
  3160. nicIsochFreeResources (pAdapter, hResource);
  3161. FALL_THROUGH
  3162. }
  3163. case StartState:
  3164. {
  3165. FALL_THROUGH
  3166. }
  3167. default:
  3168. {
  3169. break;
  3170. }
  3171. }
  3172. VC_ACQUIRE_LOCK (pChannelVc);
  3173. //
  3174. // Update Flags in the VC structure
  3175. //
  3176. VC_SET_FLAG (pChannelVc, VCBF_FreedResources);
  3177. fAllocatedChannel = VC_TEST_FLAGS( pChannelVc, VCBF_AllocatedChannel);
  3178. //
  3179. // Do we need to free a channel as well
  3180. //
  3181. if (fAllocatedChannel == TRUE)
  3182. {
  3183. Channel = pChannelVc->Channel;
  3184. pChannelVc->Channel = INVALID_CHANNEL;
  3185. nicDereferenceCall ((PVCCB) pChannelVc, "Free Allocated Channel");
  3186. }
  3187. VC_RELEASE_LOCK (pChannelVc);
  3188. if (fAllocatedChannel)
  3189. {
  3190. nicFreeChannel (pAdapter, pChannelVc->Channel);
  3191. }
  3192. } // end of failure code path
  3193. TRACE( TL_T, TM_Cm, ( "<== nicAllocateChannelResourcesAndListen NdisStatus %x ",NdisStatus) );
  3194. MATCH_IRQL;
  3195. return NdisStatus;
  3196. }
  3197. NDIS_STATUS
  3198. nicQueryRemoteNodeCaps (
  3199. IN PADAPTERCB pAdapter,
  3200. IN PREMOTE_NODE pRemoteNode,
  3201. OUT PULONG pSpeedTo,
  3202. OUT PULONG pMaxBufferSize,
  3203. OUT PULONG pMaxRec
  3204. )
  3205. /*++
  3206. Routine Description:
  3207. Queries the remote Node for speed and max size
  3208. Arguments:
  3209. pSpeedTo -- max speed to the remote node. From nodes config rom.
  3210. in units of SCODE_XXX_RATE.
  3211. pMaxBufferSize -- max buffer size to use ( this is the min of local,
  3212. remote and max allowed by *pSpeedTo).
  3213. pMaxRec -- maxrec of the remote node -- from the node's config
  3214. rom.
  3215. Return Value:
  3216. --*/
  3217. {
  3218. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  3219. ULONG Speed = 0; // Speed in units of SPEED_FLAG_XXX
  3220. ULONG MaxBufferSize;
  3221. PVOID pCRom = NULL;
  3222. PCONFIG_ROM pBusInfo = NULL;
  3223. ULONG SpeedMaxRec = 0;
  3224. ULONG MaxRec= 0;
  3225. ULONG MinMaxRec= 0;
  3226. TRACE( TL_T, TM_Cm, ( "==> nicQueryRemoteNodeCaps pRemoteNode%x ",pRemoteNode) );
  3227. do
  3228. {
  3229. ASSERT (KeGetCurrentIrql()==PASSIVE_LEVEL);
  3230. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3231. if (REMOTE_NODE_ACTIVE (pRemoteNode) == FALSE)
  3232. {
  3233. NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
  3234. ADAPTER_RELEASE_LOCK (pAdapter);
  3235. break;
  3236. }
  3237. ADAPTER_RELEASE_LOCK (pAdapter);
  3238. NdisStatus = nicGetMaxSpeedBetweenDevices (pAdapter,
  3239. 1 ,
  3240. &pRemoteNode->pPdo,
  3241. &Speed);
  3242. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3243. {
  3244. BREAK (TM_Cm, (" nicQueryRemoteNodeCaps : nicGetMaxSpeedBetweenDevices FAILED") );
  3245. }
  3246. TRACE( TL_V, TM_Cm, ( "nicGetMaxSpeedBetweenDevices Speed %x ",Speed) );
  3247. //
  3248. // This is the MaxRec from the Actual speed of
  3249. // the link.
  3250. //
  3251. SpeedMaxRec = nicGetMaxRecFromSpeed(Speed);
  3252. //
  3253. // Now get the max rec from the config rom
  3254. //
  3255. NdisStatus = nicGetConfigRom (pRemoteNode->pPdo, &pCRom);
  3256. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3257. {
  3258. BREAK (TM_Cm, (" nicQueryRemoteNodeCaps : nicGetMaxSpeedBetweenDevices FAILED") );
  3259. }
  3260. //
  3261. // Now extract the bus info, and get the remoteNode's MaxRec
  3262. // The max rec is a 4-bit field at location 0x0000f000.
  3263. // See for example Figure 11-3: Format of the Bus_Info_Block in
  3264. // the Mind Share Inc's FireWire System Architecture book.
  3265. //
  3266. //
  3267. pBusInfo = (PCONFIG_ROM) pCRom;
  3268. MaxRec = SWAPBYTES_ULONG (pBusInfo->CR_BusInfoBlockCaps);
  3269. MaxRec &= 0xf000;
  3270. MaxRec = MaxRec >> 12;
  3271. //
  3272. // Take the minimum of the adapter, the remote node
  3273. // and the link's maxRec
  3274. //
  3275. MinMaxRec = min (MaxRec, pAdapter->MaxRec);
  3276. MinMaxRec = min (MinMaxRec, SpeedMaxRec);
  3277. switch (MinMaxRec)
  3278. {
  3279. case MAX_REC_100_RATE:
  3280. {
  3281. MaxBufferSize = ASYNC_PAYLOAD_100_RATE ;
  3282. break;
  3283. }
  3284. case MAX_REC_200_RATE:
  3285. {
  3286. MaxBufferSize = ASYNC_PAYLOAD_200_RATE;
  3287. break;
  3288. }
  3289. case MAX_REC_400_RATE :
  3290. {
  3291. MaxBufferSize = ASYNC_PAYLOAD_400_RATE;
  3292. break;
  3293. }
  3294. default:
  3295. {
  3296. //
  3297. // Use the 400 size for all larger payloads.
  3298. //
  3299. MaxBufferSize = ASYNC_PAYLOAD_400_RATE;
  3300. break;
  3301. }
  3302. }
  3303. TRACE( TL_N, TM_Cm, (" MaxRec %x\n", MaxRec ) );
  3304. } while (FALSE);
  3305. if (NdisStatus == NDIS_STATUS_SUCCESS)
  3306. {
  3307. Speed = nicSpeedFlagsToSCode(Speed);
  3308. *pSpeedTo = Speed;
  3309. *pMaxBufferSize = MaxBufferSize;
  3310. *pMaxRec = MaxRec;
  3311. // Update the remote node's cached caps.
  3312. //
  3313. REMOTE_NODE_ACQUIRE_LOCK (pRemoteNode);
  3314. pRemoteNode->CachedCaps.SpeedTo = Speed;
  3315. pRemoteNode->CachedCaps.EffectiveMaxBufferSize = MaxBufferSize;
  3316. pRemoteNode->CachedCaps.MaxRec = MaxRec;
  3317. REMOTE_NODE_RELEASE_LOCK (pRemoteNode);
  3318. }
  3319. if (pCRom != NULL)
  3320. {
  3321. FREE_NONPAGED (pCRom);
  3322. }
  3323. TRACE( TL_T, TM_Cm, ( "<== nicQueryRemoteNodeCaps pRemoteNode%x , NdisStatus %x",pRemoteNode, NdisStatus) );
  3324. return NdisStatus;
  3325. }
  3326. VOID
  3327. nicInterceptMakeCallParameters (
  3328. PCO_MEDIA_PARAMETERS pMedia
  3329. )
  3330. {
  3331. PNIC1394_MEDIA_PARAMETERS p1394Params = (PNIC1394_MEDIA_PARAMETERS )(pMedia->MediaSpecific.Parameters);
  3332. #if INTERCEPT_MAKE_CALL
  3333. if (p1394Params->Destination.AddressType == NIC1394AddressType_MultiChannel)
  3334. {
  3335. p1394Params->Destination.AddressType = NIC1394AddressType_Channel;
  3336. p1394Params->Destination.Channel = 0x3a;
  3337. p1394Params->Flags |= NIC1394_VCFLAG_ALLOCATE;
  3338. pMedia->Flags |= TRANSMIT_VC;
  3339. pMedia->Flags &= (~RECEIVE_VC);
  3340. return;
  3341. }
  3342. if (p1394Params->Destination.AddressType == NIC1394AddressType_Ethernet)
  3343. {
  3344. p1394Params->Destination.AddressType = NIC1394AddressType_Channel;
  3345. p1394Params->Destination.Channel = 0x3a;
  3346. pMedia->Flags |= RECEIVE_VC;
  3347. pMedia->Flags &= (~TRANSMIT_VC);
  3348. return;
  3349. }
  3350. #endif
  3351. }
  3352. UINT
  3353. nicSpeedFlagsToSCode(
  3354. IN UINT SpeedFlags
  3355. )
  3356. {
  3357. UINT SCode = SCODE_400_RATE;
  3358. switch (SpeedFlags)
  3359. {
  3360. case SPEED_FLAGS_100 :
  3361. {
  3362. SCode = SCODE_100_RATE;
  3363. break;
  3364. }
  3365. case SPEED_FLAGS_200 :
  3366. {
  3367. SCode = SCODE_200_RATE;
  3368. break;
  3369. }
  3370. case SPEED_FLAGS_400 :
  3371. {
  3372. SCode = SCODE_400_RATE;
  3373. break;
  3374. }
  3375. case SPEED_FLAGS_800 :
  3376. {
  3377. SCode = SCODE_800_RATE;
  3378. break;
  3379. }
  3380. case SPEED_FLAGS_1600 :
  3381. {
  3382. SCode = SCODE_1600_RATE;
  3383. break;
  3384. }
  3385. case SPEED_FLAGS_3200 :
  3386. {
  3387. SCode = SCODE_3200_RATE;
  3388. break;
  3389. }
  3390. default :
  3391. {
  3392. ASSERT (!"SpeedFlags out of range");
  3393. break;
  3394. }
  3395. }
  3396. return SCode;
  3397. }