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.

5577 lines
130 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. callmgr.c - Call Manager Interface routines.
  5. Abstract:
  6. Call Manager Interface routines for the ATMARP Client, including
  7. NDIS entry points for that interface.
  8. Revision History:
  9. Who When What
  10. -------- -------- ----------------------------------------------
  11. arvindm 02-15-96 Created
  12. Notes:
  13. --*/
  14. #include <precomp.h>
  15. #define _FILENUMBER 'RGMC'
  16. VOID
  17. AtmArpCoAfRegisterNotifyHandler(
  18. IN NDIS_HANDLE ProtocolBindingContext,
  19. IN PCO_ADDRESS_FAMILY pAddressFamily
  20. )
  21. /*++
  22. Routine Description:
  23. This routine is called by NDIS when a Call manager registers its support
  24. for an Address Family over an adapter. If this is the Address Family we
  25. are interested in (UNI 3.1), then we start up all LIS' configured on
  26. this adapter.
  27. Arguments:
  28. ProtocolBindingContext - our context passed in NdisOpenAdapter, which is
  29. a pointer to our Adapter structure.
  30. pAddressFamily - points to a structure describing the Address Family
  31. being registered by a Call Manager.
  32. Return Value:
  33. None
  34. --*/
  35. {
  36. PATMARP_ADAPTER pAdapter;
  37. PATMARP_INTERFACE pInterface; // Pointer to new ATMARP Interface
  38. ULONG NumIFConfigured; // # of LIS' over this adapter
  39. ULONG NumIFActivated; // # activated successfully here
  40. NDIS_STATUS Status;
  41. NDIS_HANDLE LISConfigHandle; // Handle to per-LIS config
  42. struct LLIPBindInfo BindInfo;
  43. BOOLEAN bProcessingAf;
  44. //
  45. // Initialize.
  46. //
  47. Status = NDIS_STATUS_SUCCESS;
  48. pAdapter = NULL_PATMARP_ADAPTER;
  49. LISConfigHandle = NULL;
  50. NumIFActivated = 0;
  51. bProcessingAf = FALSE;
  52. do
  53. {
  54. //
  55. // Check if this AF is interesting to us.
  56. //
  57. if ((pAddressFamily->AddressFamily != CO_ADDRESS_FAMILY_Q2931) ||
  58. (pAddressFamily->MajorVersion != 3) ||
  59. (pAddressFamily->MinorVersion != 1))
  60. {
  61. AADEBUGP(AAD_LOUD,
  62. ("CoAfRegisterNotifyHandler: uninteresting AF %d or MajVer %d or MinVer %d\n",
  63. pAddressFamily->AddressFamily,
  64. pAddressFamily->MajorVersion,
  65. pAddressFamily->MinorVersion));
  66. Status = NDIS_STATUS_NOT_RECOGNIZED;
  67. break;
  68. }
  69. pAdapter = (PATMARP_ADAPTER)ProtocolBindingContext;
  70. AA_STRUCT_ASSERT(pAdapter, aaa);
  71. AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  72. if (pAdapter->Flags & AA_ADAPTER_FLAGS_UNBINDING)
  73. {
  74. AADEBUGP(AAD_INFO,
  75. ("CoAfRegisterNotify: Adapter %x is unbinding, bailing out\n", pAdapter));
  76. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  77. Status = NDIS_STATUS_FAILURE;
  78. break;
  79. }
  80. //
  81. // If we have already created LIS' on this adapter, we don't want
  82. // to open this Call Manager (multiple Call Managers supporting the
  83. // same AF on the same adapter?)
  84. //
  85. if (pAdapter->pInterfaceList != NULL_PATMARP_INTERFACE)
  86. {
  87. AADEBUGP(AAD_WARNING,
  88. ("CoAfRegisterNotifyHandler: pAdapter 0x%x, IFs (%x) already created!\n",
  89. pAdapter, pAdapter->pInterfaceList));
  90. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  91. Status = NDIS_STATUS_FAILURE;
  92. break;
  93. }
  94. if (pAdapter->Flags & AA_ADAPTER_FLAGS_PROCESSING_AF)
  95. {
  96. AADEBUGP(AAD_WARNING,
  97. ("CoAfRegisterNotifyHandler: pAdapter 0x%x, Already processing AF!\n",
  98. pAdapter));
  99. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  100. Status = NDIS_STATUS_FAILURE;
  101. break;
  102. }
  103. //
  104. // Make sure that we don't let an UnbindAdapter thread preempt us.
  105. //
  106. AA_INIT_BLOCK_STRUCT(&pAdapter->UnbindBlock);
  107. pAdapter->Flags |= AA_ADAPTER_FLAGS_PROCESSING_AF;
  108. bProcessingAf = TRUE;
  109. if (pAdapter->Flags & AA_ADAPTER_FLAGS_AF_NOTIFIED)
  110. {
  111. //
  112. // This can happen when resuming from suspend/hibernate, since
  113. // we do not get unbound from the adapter. All IFs go away,
  114. // but the adapter remains.
  115. //
  116. // So we skip the one-time init stuff (see below), but go ahead
  117. // and process the AF and create IFs now.
  118. //
  119. AADEBUGP(AAD_WARNING,
  120. ("CoAfRegisterNotify: Adapter %x seen AF notify already, Flags %x\n",
  121. pAdapter, pAdapter->Flags));
  122. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  123. }
  124. else
  125. {
  126. //
  127. // Do one-time init stuff for this adapter.
  128. //
  129. pAdapter->Flags |= AA_ADAPTER_FLAGS_AF_NOTIFIED;
  130. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  131. //
  132. // Query the adapter (miniport) for information about the adapter
  133. // we are bound to.
  134. //
  135. Status = AtmArpGetAdapterInfo(pAdapter);
  136. if (Status != NDIS_STATUS_SUCCESS)
  137. {
  138. AADEBUGP(AAD_WARNING,
  139. ("CoAfRegisterNotifyHandler: Failed to get adapter info.\n"));
  140. break;
  141. }
  142. //
  143. // Read the adapter's configuration information from the registry.
  144. //
  145. Status = AtmArpCfgReadAdapterConfiguration(pAdapter);
  146. if (Status != NDIS_STATUS_SUCCESS)
  147. {
  148. AADEBUGP(AAD_WARNING,
  149. ("CoAfRegisterNotifyHandler: Failed to open adapter configuration\n"));
  150. break;
  151. }
  152. }
  153. AADEBUGP(AAD_WARNING,
  154. ("CoAfRegisterNotify: Adapter %x/%x, starting up\n", pAdapter, pAdapter->Flags));
  155. //
  156. // Initialize some variables so that we know if we failed
  157. // somewhere in the following loop.
  158. //
  159. LISConfigHandle = NULL;
  160. pInterface = NULL_PATMARP_INTERFACE;
  161. //
  162. // Set up IP and NDIS interfaces for each LIS configured
  163. // for this adapter. Loop while there are more LIS'.
  164. //
  165. for (NumIFConfigured = 0;
  166. ; // Stop only on error or no more LIS
  167. NumIFConfigured++)
  168. {
  169. #ifdef NEWARP
  170. //
  171. // TCP/IP's Configuration section for this interface.
  172. //
  173. NDIS_STRING IPConfigString;
  174. #endif // NEWARP
  175. //
  176. // Process LIS # NumIFConfigured.
  177. //
  178. // Open the configuration section for this LIS. We use
  179. // "NumIFConfigured" as the index of the LIS to be opened.
  180. //
  181. LISConfigHandle = AtmArpCfgOpenLISConfiguration(
  182. pAdapter,
  183. NumIFConfigured
  184. #ifdef NEWARP
  185. ,
  186. &IPConfigString
  187. #endif // NEWARP
  188. );
  189. if (LISConfigHandle == NULL)
  190. {
  191. //
  192. // This is the normal termination condition, i.e.
  193. // we reached the end of the LIS list for this
  194. // adapter.
  195. //
  196. AADEBUGP(AAD_INFO, ("NotifyRegAfHandler: cannot open LIS %d\n",
  197. NumIFConfigured));
  198. Status = NDIS_STATUS_SUCCESS;
  199. break; // out of for loop
  200. }
  201. pInterface = AtmArpAddInterfaceToAdapter (
  202. pAdapter,
  203. LISConfigHandle,
  204. &IPConfigString
  205. );
  206. //
  207. // Close the configuration section for this LIS.
  208. //
  209. AtmArpCfgCloseLISConfiguration(LISConfigHandle);
  210. LISConfigHandle = NULL;
  211. if (pInterface == NULL_PATMARP_INTERFACE)
  212. {
  213. Status = NDIS_STATUS_FAILURE;
  214. break;
  215. }
  216. } // for
  217. }
  218. while (FALSE);
  219. if (NumIFActivated > 0)
  220. {
  221. //
  222. // We managed to activate atleast one Logical IP Subnet
  223. // on this adapter.
  224. //
  225. pAdapter->InterfaceCount = NumIFActivated;
  226. }
  227. if (bProcessingAf)
  228. {
  229. AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  230. pAdapter->Flags &= ~AA_ADAPTER_FLAGS_PROCESSING_AF;
  231. AA_SIGNAL_BLOCK_STRUCT(&pAdapter->UnbindBlock, NDIS_STATUS_SUCCESS);
  232. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  233. }
  234. return;
  235. }
  236. NDIS_STATUS
  237. AtmArpOpenCallMgr(
  238. IN PATMARP_INTERFACE pInterface
  239. )
  240. /*++
  241. Routine Description:
  242. Start access to the Call Manager on the specified Interface,
  243. by doing the following:
  244. - Open Address Family
  245. For all of these, we wait for completion in case they pend.
  246. It is assumed that the Interface structure is locked.
  247. Arguments:
  248. pInterface - pointer to the ATMARP interface
  249. Return Value:
  250. NDIS status.
  251. --*/
  252. {
  253. PCO_ADDRESS_FAMILY pAddressFamily;
  254. NDIS_STATUS Status;
  255. ULONG RequestSize;
  256. pAddressFamily = (PCO_ADDRESS_FAMILY)NULL;
  257. Status = NDIS_STATUS_SUCCESS;
  258. do {
  259. //
  260. // Allocate everything we need
  261. //
  262. RequestSize = sizeof(CO_ADDRESS_FAMILY)+
  263. sizeof(CO_SAP)+
  264. sizeof(ATM_SAP)+
  265. sizeof(ATM_ADDRESS);
  266. AA_ALLOC_MEM(
  267. pAddressFamily,
  268. CO_ADDRESS_FAMILY,
  269. RequestSize
  270. );
  271. if (pAddressFamily == (PCO_ADDRESS_FAMILY)NULL)
  272. {
  273. AADEBUGP(AAD_ERROR, ("OpenCallMgr: alloc failed!\n"));
  274. Status = NDIS_STATUS_RESOURCES;
  275. break;
  276. }
  277. //
  278. // DONT remove the following
  279. //
  280. AA_SET_MEM((PUCHAR)pAddressFamily, 0, RequestSize);
  281. //
  282. // The Address Family we are interested in is Q.2931 (UNI 3.1)
  283. //
  284. pAddressFamily->AddressFamily = CO_ADDRESS_FAMILY_Q2931;
  285. pAddressFamily->MajorVersion = 3;
  286. pAddressFamily->MinorVersion = 1;
  287. AA_INIT_BLOCK_STRUCT(&(pInterface->Block));
  288. Status = NdisClOpenAddressFamily(
  289. pInterface->NdisAdapterHandle,
  290. pAddressFamily,
  291. (NDIS_HANDLE)pInterface,
  292. &AtmArpClientCharacteristics,
  293. sizeof(AtmArpClientCharacteristics),
  294. &(pInterface->NdisAfHandle)
  295. );
  296. if (Status == NDIS_STATUS_PENDING)
  297. {
  298. //
  299. // Wait for completion
  300. //
  301. Status = AA_WAIT_ON_BLOCK_STRUCT(&(pInterface->Block));
  302. }
  303. if (Status != NDIS_STATUS_SUCCESS)
  304. {
  305. AADEBUGP(AAD_ERROR, ("Open Af returned error: 0x%x\n", Status));
  306. break;
  307. }
  308. AADEBUGP(AAD_INFO, ("Interface: 0x%x, Got NdisAfHandle: 0x%x\n",
  309. pInterface, pInterface->NdisAfHandle));
  310. break;
  311. }
  312. while (FALSE);
  313. if (pAddressFamily != (PCO_ADDRESS_FAMILY)NULL)
  314. {
  315. AA_FREE_MEM(pAddressFamily);
  316. }
  317. AADEBUGP(AAD_LOUD, ("Open Call Mgr returning 0x%x\n", Status));
  318. return (Status);
  319. }
  320. VOID
  321. AtmArpCloseCallMgr(
  322. IN PATMARP_INTERFACE pInterface
  323. )
  324. /*++
  325. Routine Description:
  326. Halt access to the Call Manager on the specified interface. It is
  327. assumed that all VCs and SAPs pertaining to the "Address Family Open"
  328. have been released.
  329. Arguments:
  330. pInterface - pointer to the ATMARP interface
  331. Return Value:
  332. None
  333. --*/
  334. {
  335. NDIS_STATUS Status;
  336. NDIS_HANDLE NdisAfHandle;
  337. NdisAfHandle = pInterface->NdisAfHandle;
  338. pInterface->NdisAfHandle = NULL;
  339. AADEBUGP(AAD_INFO,
  340. ("Closing Call Mgr on Interface: 0x%x, AfH: 0x%x\n",
  341. pInterface, NdisAfHandle));
  342. if (NdisAfHandle != (NDIS_HANDLE)NULL)
  343. {
  344. Status = NdisClCloseAddressFamily(NdisAfHandle);
  345. AADEBUGP(AAD_INFO, ("NdisClCloseAF on IF 0x%x returned 0x%x\n",
  346. pInterface, Status));
  347. if (Status != NDIS_STATUS_PENDING)
  348. {
  349. AtmArpCloseAfCompleteHandler(
  350. Status,
  351. (NDIS_HANDLE)pInterface
  352. );
  353. }
  354. }
  355. }
  356. VOID
  357. AtmArpRegisterSaps(
  358. IN PATMARP_INTERFACE pInterface
  359. )
  360. /*++
  361. Routine Description:
  362. Register all SAPs configured on the given ATMARP interface.
  363. Atleast one SAP must be present in the list of SAPs on the
  364. interface.
  365. We just issue the NdisClRegisterSap requests for all SAPs.
  366. We don't wait for completion.
  367. Arguments:
  368. pInterface - Pointer to ATMARP Interface
  369. Return Value:
  370. None
  371. --*/
  372. {
  373. PATMARP_SAP pAtmArpSap;
  374. PATMARP_SAP pNextSap;
  375. PCO_SAP pSapInfo;
  376. NDIS_STATUS Status;
  377. NDIS_HANDLE NdisAfHandle;
  378. ULONG rc; // Ref count on Interface
  379. AA_ACQUIRE_IF_LOCK(pInterface);
  380. AA_ASSERT(pInterface->NumberOfSaps > 0);
  381. //
  382. // Initialize
  383. //
  384. pAtmArpSap = &(pInterface->SapList);
  385. NdisAfHandle = pInterface->NdisAfHandle;
  386. //
  387. // Make sure that the Interface doesn't go away.
  388. //
  389. AtmArpReferenceInterface(pInterface);
  390. AA_RELEASE_IF_LOCK(pInterface);
  391. do
  392. {
  393. pSapInfo = pAtmArpSap->pInfo;
  394. pAtmArpSap->NdisSapHandle = NULL;
  395. AA_SET_FLAG(pAtmArpSap->Flags,
  396. AA_SAP_REG_STATE_MASK,
  397. AA_SAP_REG_STATE_REGISTERING);
  398. pNextSap = pAtmArpSap->pNextSap;
  399. //
  400. // The ATMARP SAP structure itself won't go away as long as
  401. // the Interface structure lives.
  402. //
  403. Status = NdisClRegisterSap(
  404. NdisAfHandle,
  405. (NDIS_HANDLE)pAtmArpSap, // ProtocolSapContext
  406. pSapInfo,
  407. &(pAtmArpSap->NdisSapHandle)
  408. );
  409. if (Status != NDIS_STATUS_PENDING)
  410. {
  411. AtmArpRegisterSapCompleteHandler(
  412. Status,
  413. (NDIS_HANDLE)pAtmArpSap,
  414. pSapInfo,
  415. pAtmArpSap->NdisSapHandle
  416. );
  417. }
  418. pAtmArpSap = pNextSap;
  419. }
  420. while (pAtmArpSap != NULL_PATMARP_SAP);
  421. //
  422. // Remove the reference we added earlier to the Interface.
  423. //
  424. AA_ACQUIRE_IF_LOCK(pInterface);
  425. rc = AtmArpDereferenceInterface(pInterface);
  426. if (rc > 0)
  427. {
  428. AA_RELEASE_IF_LOCK(pInterface);
  429. }
  430. //
  431. // else the Interface is gone!
  432. }
  433. VOID
  434. AtmArpDeregisterSaps(
  435. IN PATMARP_INTERFACE pInterface
  436. )
  437. /*++
  438. Routine Description:
  439. Deregister all SAPs on an ATMARP Interface. We issue NdisClDeregisterSap
  440. calls on all SAPs we have currently registered.
  441. Arguments:
  442. pInterface - Pointer to ATMARP Interface
  443. Return Value:
  444. None
  445. --*/
  446. {
  447. NDIS_HANDLE NdisSapHandle;
  448. ULONG rc; // Reference count on Interface
  449. PATMARP_SAP pAtmArpSap;
  450. PATMARP_SAP pNextSap;
  451. NDIS_STATUS Status;
  452. AA_ACQUIRE_IF_LOCK(pInterface);
  453. //
  454. // Initialize
  455. //
  456. pAtmArpSap = &(pInterface->SapList);
  457. //
  458. // Make sure the Interface structure doesn't go away.
  459. //
  460. AtmArpReferenceInterface(pInterface);
  461. AA_RELEASE_IF_LOCK(pInterface);
  462. do
  463. {
  464. NdisSapHandle = pAtmArpSap->NdisSapHandle;
  465. pNextSap = pAtmArpSap->pNextSap;
  466. if (NdisSapHandle != NULL)
  467. {
  468. Status = NdisClDeregisterSap(NdisSapHandle);
  469. if (Status != NDIS_STATUS_PENDING)
  470. {
  471. AtmArpDeregisterSapCompleteHandler(
  472. Status,
  473. (NDIS_HANDLE)pAtmArpSap
  474. );
  475. }
  476. }
  477. pAtmArpSap = pNextSap;
  478. }
  479. while (pAtmArpSap != NULL_PATMARP_SAP);
  480. //
  481. // Remove the reference we added earlier to the Interface.
  482. //
  483. AA_ACQUIRE_IF_LOCK(pInterface);
  484. rc = AtmArpDereferenceInterface(pInterface);
  485. if (rc > 0)
  486. {
  487. AA_RELEASE_IF_LOCK(pInterface);
  488. }
  489. //
  490. // else the interface is gone
  491. //
  492. }
  493. NDIS_STATUS
  494. AtmArpMakeCall(
  495. IN PATMARP_INTERFACE pInterface,
  496. IN PATMARP_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT,
  497. IN PATMARP_FLOW_SPEC pFlowSpec,
  498. IN PNDIS_PACKET pPacketToBeQueued OPTIONAL
  499. )
  500. /*++
  501. Routine Description:
  502. Place a call to the given destination. Map the specified flow
  503. specs to ATM QoS/Traffic parameters.
  504. NOTE: The caller is assumed to hold a lock for the ATM Entry,
  505. which will be released here. The reason we do it this way is so that
  506. nobody else can come in and try to make another call (of the same kind)
  507. to this ATM Entry -- once we get a new VC into the ATM Entry's list,
  508. we can release its lock.
  509. SIDE EFFECT: If the NDIS call doesn't pend, then we call our
  510. MakeCall completion handler from here, and return NDIS_STATUS_PENDING
  511. to the caller.
  512. Arguments:
  513. pInterface - the ARP Interface originating this call
  514. pAtmEntry - Pointer to ATM Address Entry corresponding to the
  515. called address.
  516. pFlowSpec - pointer to a Flow Spec structure containing parameters
  517. for the call
  518. pPacketToBeQueued - Optionally, a packet to be queued for transmission when
  519. the call is established.
  520. Return Value:
  521. If there is an immediate failure (e.g. allocation failure), we return
  522. NDIS_STATUS_XXX denoting that failure.
  523. If we made it to the call to NdisClMakeCall(), we return NDIS_STATUS_PENDING.
  524. However, if NDIS returns other than NDIS_STATUS_PENDING, we'd also
  525. call our MakeCall completion handler.
  526. --*/
  527. {
  528. //
  529. // New VC structure to be allocated for this call
  530. //
  531. PATMARP_VC pVc;
  532. NDIS_HANDLE NdisVcHandle;
  533. NDIS_HANDLE ProtocolVcContext;
  534. NDIS_HANDLE ProtocolPartyContext;
  535. PNDIS_HANDLE pNdisPartyHandle;
  536. NDIS_STATUS Status;
  537. BOOLEAN IsPMP;
  538. PATM_ADDRESS pCalledAddress;
  539. //
  540. // Set of parameters for a MakeCall
  541. //
  542. PCO_CALL_PARAMETERS pCallParameters;
  543. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  544. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  545. //
  546. // All Info Elements that we need to fill:
  547. //
  548. Q2931_IE UNALIGNED * pIe;
  549. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  550. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  551. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  552. ATM_BLLI_IE UNALIGNED * pBlli;
  553. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  554. //
  555. // Total space requirements for the MakeCall
  556. //
  557. ULONG RequestSize;
  558. //
  559. // Did we queue the given packet?
  560. //
  561. BOOLEAN PacketWasQueued = FALSE;
  562. AA_STRUCT_ASSERT(pInterface, aai);
  563. AA_STRUCT_ASSERT(pAtmEntry, aae);
  564. AA_ASSERT(pInterface->AdminState == IF_STATUS_UP);
  565. do
  566. {
  567. if (pPacketToBeQueued != (PNDIS_PACKET)NULL)
  568. {
  569. //
  570. // Make this a list of exactly one packet.
  571. //
  572. AA_SET_NEXT_PACKET(pPacketToBeQueued, NULL);
  573. }
  574. //
  575. // Fail makecall if atmentry state is really closing.
  576. //
  577. if (AA_IS_FLAG_SET(
  578. pAtmEntry->Flags,
  579. AA_ATM_ENTRY_STATE_MASK,
  580. AA_ATM_ENTRY_CLOSING))
  581. {
  582. BOOLEAN ReallyClosing = TRUE;
  583. //
  584. // This may be a harmless close -- if the interface is not shutting
  585. // down we check if it's a harmless close, else (if the interface
  586. // is shutting down) we fail the call anyway. Note that we don't
  587. // claim the interface list lock (which is used to guard access
  588. // to AtmEntryListUp) -- we don't do this because we currently
  589. // hold the lock to pAtmEntry (and don't want to release it), so if
  590. // AtmEntryListUp is in the
  591. // process of being set to FALSE, when we read it's value here,
  592. // in the worst case we'll read it's value as TRUE and conclude that
  593. // the atm entry is not really closing and go ahead and make the call.
  594. // However in this case, the shutdown routine will invalidate the call.
  595. //
  596. if (pInterface->AtmEntryListUp)
  597. {
  598. //
  599. // WARNING: AtmArpAtmEntryIsReallyClosing may clear the
  600. // CLOSING state (if the entry is basically idle) --
  601. // see comments in that function.
  602. //
  603. ReallyClosing = AtmArpAtmEntryIsReallyClosing(pAtmEntry);
  604. }
  605. if (ReallyClosing)
  606. {
  607. AADEBUGP(AAD_FATAL,
  608. ("AtmArpMakeCall -- failing because AE 0x%lx is really closing.\n",
  609. pAtmEntry));
  610. Status = NDIS_STATUS_FAILURE;
  611. break;
  612. }
  613. }
  614. //
  615. // Some initialization.
  616. //
  617. if (AA_IS_FLAG_SET(pAtmEntry->Flags,
  618. AA_ATM_ENTRY_TYPE_MASK,
  619. AA_ATM_ENTRY_TYPE_UCAST))
  620. {
  621. IsPMP = FALSE;
  622. ProtocolPartyContext = NULL;
  623. pNdisPartyHandle = NULL;
  624. pCalledAddress = &(pAtmEntry->ATMAddress);
  625. }
  626. #ifdef IPMCAST
  627. else
  628. {
  629. IsPMP = TRUE;
  630. ProtocolPartyContext = (NDIS_HANDLE)(pAtmEntry->pMcAtmInfo->pMcAtmEntryList);
  631. pNdisPartyHandle = &(pAtmEntry->pMcAtmInfo->pMcAtmEntryList->NdisPartyHandle);
  632. pCalledAddress = &(pAtmEntry->pMcAtmInfo->pMcAtmEntryList->ATMAddress);
  633. }
  634. #else
  635. else
  636. {
  637. AA_ASSERT(FALSE);
  638. }
  639. #endif // IPMCAST
  640. //
  641. // Compute all the space needed for the MakeCall, and allocate it
  642. // in one big block.
  643. //
  644. RequestSize = sizeof(CO_CALL_PARAMETERS) +
  645. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  646. sizeof(Q2931_CALLMGR_PARAMETERS) +
  647. ATMARP_MAKE_CALL_IE_SPACE +
  648. 0;
  649. AA_ALLOC_MEM(pCallParameters, CO_CALL_PARAMETERS, RequestSize);
  650. if (pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  651. {
  652. AADEBUGP(AAD_WARNING, ("Make Call: alloc (%d) failed\n", RequestSize));
  653. Status = NDIS_STATUS_RESOURCES;
  654. break;
  655. }
  656. //
  657. // Allocate a VC structure for the call
  658. //
  659. pVc = AtmArpAllocateVc(pInterface);
  660. if (pVc == NULL_PATMARP_VC)
  661. {
  662. AADEBUGP(AAD_WARNING, ("Make Call: failed to allocate VC\n"));
  663. AA_FREE_MEM(pCallParameters);
  664. Status = NDIS_STATUS_RESOURCES;
  665. break;
  666. }
  667. //
  668. // For a later call to MakeCallComplete
  669. //
  670. ProtocolVcContext = (NDIS_HANDLE)pVc;
  671. //
  672. // Get an NDIS handle for this VC
  673. //
  674. NdisVcHandle = (NDIS_HANDLE)NULL;
  675. Status = NdisCoCreateVc(
  676. pInterface->NdisAdapterHandle,
  677. pInterface->NdisAfHandle,
  678. ProtocolVcContext,
  679. &NdisVcHandle
  680. );
  681. if (Status != NDIS_STATUS_SUCCESS)
  682. {
  683. AA_ASSERT(Status != NDIS_STATUS_PENDING);
  684. AADEBUGP(AAD_WARNING, ("Make Call: NdisCoCreateVc failed: 0x%x\n", Status));
  685. AA_FREE_MEM(pCallParameters);
  686. AtmArpDeallocateVc(pVc);
  687. break;
  688. }
  689. AADEBUGP(AAD_VERY_LOUD,
  690. ("Make Call: pAtmEntry 0x%x, pVc 0x%x, got NdisVcHandle 0x%x\n",
  691. pAtmEntry,
  692. pVc,
  693. NdisVcHandle));
  694. AtmArpReferenceVc(pVc); // CreateVC reference
  695. //
  696. // At this point, we are sure that we will call NdisClMakeCall.
  697. //
  698. //
  699. // Now fill in the rest of the VC structure. We don't need a lock
  700. // for the VC until it gets linked to the ATM Entry structure.
  701. //
  702. pVc->NdisVcHandle = NdisVcHandle;
  703. pVc->Flags = AA_VC_TYPE_SVC |
  704. AA_VC_OWNER_IS_ATMARP |
  705. AA_VC_CALL_STATE_OUTGOING_IN_PROGRESS;
  706. if (IsPMP)
  707. {
  708. pVc->Flags |= AA_VC_CONN_TYPE_PMP;
  709. }
  710. else
  711. {
  712. pVc->Flags |= AA_VC_CONN_TYPE_P2P;
  713. }
  714. pVc->FlowSpec = *pFlowSpec;
  715. //
  716. // Make sure that the packet sizes are within the miniport's range.
  717. //
  718. if (pVc->FlowSpec.SendMaxSize > pInterface->pAdapter->MaxPacketSize)
  719. {
  720. pVc->FlowSpec.SendMaxSize = pInterface->pAdapter->MaxPacketSize;
  721. }
  722. if (pVc->FlowSpec.ReceiveMaxSize > pInterface->pAdapter->MaxPacketSize)
  723. {
  724. pVc->FlowSpec.ReceiveMaxSize = pInterface->pAdapter->MaxPacketSize;
  725. }
  726. if (pPacketToBeQueued != (PNDIS_PACKET)NULL)
  727. {
  728. pVc->PacketList = pPacketToBeQueued;
  729. PacketWasQueued = TRUE;
  730. }
  731. #ifdef IPMCAST
  732. AtmArpFillCallParameters(
  733. pCallParameters,
  734. RequestSize,
  735. pCalledAddress,
  736. &(pInterface->LocalAtmAddress), // Calling address
  737. &(pVc->FlowSpec),
  738. IsPMP,
  739. TRUE // IsMakeCall?
  740. );
  741. #else
  742. //
  743. // Zero out everything
  744. //
  745. AA_SET_MEM((PUCHAR)pCallParameters, 0, RequestSize);
  746. //
  747. // Distribute space amongst the various structures
  748. //
  749. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  750. ((PUCHAR)pCallParameters +
  751. sizeof(CO_CALL_PARAMETERS));
  752. //
  753. // Set pointers to link the above structures together
  754. //
  755. pCallParameters->CallMgrParameters = pCallMgrParameters;
  756. pCallParameters->MediaParameters = (PCO_MEDIA_PARAMETERS)NULL;
  757. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  758. pCallMgrParameters->CallMgrSpecific.Length =
  759. sizeof(Q2931_CALLMGR_PARAMETERS) +
  760. ATMARP_CALL_IE_SPACE;
  761. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  762. pCallMgrParameters->CallMgrSpecific.Parameters;
  763. //
  764. // Call Manager generic flow parameters:
  765. //
  766. pCallMgrParameters->Transmit.TokenRate = (pFlowSpec->SendAvgBandwidth);
  767. pCallMgrParameters->Transmit.TokenBucketSize = (pFlowSpec->SendMaxSize);
  768. pCallMgrParameters->Transmit.MaxSduSize = pFlowSpec->SendMaxSize;
  769. pCallMgrParameters->Transmit.PeakBandwidth = (pFlowSpec->SendPeakBandwidth);
  770. pCallMgrParameters->Transmit.ServiceType = pFlowSpec->SendServiceType;
  771. pCallMgrParameters->Receive.TokenRate = (pFlowSpec->ReceiveAvgBandwidth);
  772. pCallMgrParameters->Receive.TokenBucketSize = pFlowSpec->ReceiveMaxSize;
  773. pCallMgrParameters->Receive.MaxSduSize = pFlowSpec->ReceiveMaxSize;
  774. pCallMgrParameters->Receive.PeakBandwidth = (pFlowSpec->ReceivePeakBandwidth);
  775. pCallMgrParameters->Receive.ServiceType = pFlowSpec->ReceiveServiceType;
  776. //
  777. // Q2931 Call Manager Parameters:
  778. //
  779. //
  780. // Called address:
  781. //
  782. // TBD: Add Called Subaddress IE in outgoing call.
  783. //
  784. AA_COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CalledParty),
  785. (PUCHAR)&(pAtmEntry->ATMAddress),
  786. sizeof(ATM_ADDRESS));
  787. //
  788. // Calling address:
  789. //
  790. AA_COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CallingParty),
  791. (PUCHAR)&(pInterface->LocalAtmAddress),
  792. sizeof(ATM_ADDRESS));
  793. //
  794. // RFC 1755 (Sec 5) says that the following IEs MUST be present in the
  795. // SETUP message, so fill them all.
  796. //
  797. // AAL Parameters
  798. // Traffic Descriptor
  799. // Broadband Bearer Capability
  800. // Broadband Low Layer Info
  801. // QoS
  802. //
  803. //
  804. // Initialize the Info Element list
  805. //
  806. pAtmCallMgrParameters->InfoElementCount = 0;
  807. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  808. //
  809. // AAL Parameters:
  810. //
  811. {
  812. UNALIGNED AAL5_PARAMETERS *pAal5;
  813. pIe->IEType = IE_AALParameters;
  814. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  815. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  816. pAalIe->AALType = AAL_TYPE_AAL5;
  817. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  818. pAal5->ForwardMaxCPCSSDUSize = pFlowSpec->SendMaxSize;
  819. pAal5->BackwardMaxCPCSSDUSize = pFlowSpec->ReceiveMaxSize;
  820. }
  821. pAtmCallMgrParameters->InfoElementCount++;
  822. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  823. //
  824. // Traffic Descriptor:
  825. //
  826. pIe->IEType = IE_TrafficDescriptor;
  827. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE;
  828. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)pIe->IE;
  829. if (pFlowSpec->SendServiceType == SERVICETYPE_BESTEFFORT)
  830. {
  831. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  832. BYTES_TO_CELLS(pFlowSpec->SendPeakBandwidth);
  833. pTrafficDescriptor->BackwardTD.PeakCellRateCLP01 =
  834. BYTES_TO_CELLS(pFlowSpec->ReceivePeakBandwidth);
  835. pTrafficDescriptor->BestEffort = TRUE;
  836. }
  837. else
  838. {
  839. // Predictive/Guaranteed service (we map this to CBR, see BBC below)
  840. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  841. BYTES_TO_CELLS(pFlowSpec->SendPeakBandwidth);
  842. pTrafficDescriptor->BackwardTD.PeakCellRateCLP01 =
  843. BYTES_TO_CELLS(pFlowSpec->ReceivePeakBandwidth);
  844. pTrafficDescriptor->BestEffort = FALSE;
  845. }
  846. pAtmCallMgrParameters->InfoElementCount++;
  847. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  848. //
  849. // Broadband Bearer Capability
  850. //
  851. pIe->IEType = IE_BroadbandBearerCapability;
  852. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE;
  853. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)pIe->IE;
  854. pBbc->BearerClass = BCOB_X;
  855. pBbc->UserPlaneConnectionConfig = UP_P2P;
  856. if (pFlowSpec->SendServiceType == SERVICETYPE_BESTEFFORT)
  857. {
  858. pBbc->TrafficType = TT_NOIND;
  859. pBbc->TimingRequirements = TR_NOIND;
  860. pBbc->ClippingSusceptability = CLIP_NOT;
  861. }
  862. else
  863. {
  864. pBbc->TrafficType = TT_CBR;
  865. pBbc->TimingRequirements = TR_END_TO_END;
  866. pBbc->ClippingSusceptability = CLIP_SUS;
  867. }
  868. pAtmCallMgrParameters->InfoElementCount++;
  869. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  870. //
  871. // Broadband Lower Layer Information
  872. //
  873. pIe->IEType = IE_BLLI;
  874. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  875. pBlli = (PATM_BLLI_IE)pIe->IE;
  876. AA_COPY_MEM((PUCHAR)pBlli,
  877. (PUCHAR)&AtmArpDefaultBlli,
  878. sizeof(ATM_BLLI_IE));
  879. pAtmCallMgrParameters->InfoElementCount++;
  880. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  881. //
  882. // QoS
  883. //
  884. pIe->IEType = IE_QOSClass;
  885. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE;
  886. pQos = (PATM_QOS_CLASS_IE)pIe->IE;
  887. if (pFlowSpec->SendServiceType == SERVICETYPE_BESTEFFORT)
  888. {
  889. pQos->QOSClassForward = pQos->QOSClassBackward = 0;
  890. }
  891. else
  892. {
  893. pQos->QOSClassForward = pQos->QOSClassBackward = 1;
  894. }
  895. pAtmCallMgrParameters->InfoElementCount++;
  896. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  897. #endif // IPMCAST
  898. //
  899. // We add the Call reference and ATM Entry Link reference
  900. // right here
  901. //
  902. AtmArpReferenceVc(pVc); // Call reference (MakeCall coming up)
  903. AtmArpReferenceVc(pVc); // ATM Entry link reference (coming up below)
  904. #ifdef IPMCAST
  905. if (IsPMP)
  906. {
  907. pAtmEntry->pMcAtmInfo->TransientLeaves++;
  908. }
  909. #endif // IPMCAST
  910. //
  911. // We are ready to make the call. Before we do so, we need to
  912. // link the VC structure to the ATM Entry, and release the
  913. // ATM Entry lock
  914. //
  915. AtmArpLinkVcToAtmEntry(pVc, pAtmEntry);
  916. AA_RELEASE_AE_LOCK(pAtmEntry); // acquired by caller
  917. //
  918. // Make the Call now
  919. //
  920. Status = NdisClMakeCall(
  921. NdisVcHandle,
  922. pCallParameters,
  923. ProtocolPartyContext,
  924. pNdisPartyHandle
  925. );
  926. if (Status != NDIS_STATUS_PENDING)
  927. {
  928. NDIS_HANDLE NdisPartyHandle;
  929. NdisPartyHandle = ((pNdisPartyHandle != NULL)?
  930. *pNdisPartyHandle : NULL);
  931. AtmArpMakeCallCompleteHandler(
  932. Status,
  933. ProtocolVcContext,
  934. NdisPartyHandle,
  935. pCallParameters
  936. );
  937. Status = NDIS_STATUS_PENDING;
  938. }
  939. //
  940. // else the MakeCall complete handler will be called
  941. // later
  942. //
  943. } while (FALSE);
  944. if (Status != NDIS_STATUS_PENDING)
  945. {
  946. ULONG Flags;
  947. //
  948. // Something failed within this routine.
  949. // Recovery:
  950. // - Release the ATM Entry lock
  951. // - If we were given a packet for queueing, and we didn't do so,
  952. // then free it
  953. //
  954. Flags = pAtmEntry->Flags;
  955. AA_RELEASE_AE_LOCK(pAtmEntry); // acquired by caller
  956. if ((pPacketToBeQueued != (PNDIS_PACKET)NULL) && (!PacketWasQueued))
  957. {
  958. AA_HEADER_TYPE HdrType;
  959. BOOLEAN HdrPresent;
  960. if (pFlowSpec->Encapsulation == ENCAPSULATION_TYPE_LLCSNAP)
  961. {
  962. HdrPresent = TRUE;
  963. if (AA_IS_FLAG_SET(Flags,
  964. AA_ATM_ENTRY_TYPE_MASK,
  965. AA_ATM_ENTRY_TYPE_UCAST))
  966. {
  967. HdrType = AA_HEADER_TYPE_UNICAST;
  968. }
  969. else
  970. {
  971. HdrType = AA_HEADER_TYPE_NUNICAST;
  972. }
  973. }
  974. else
  975. {
  976. HdrPresent = FALSE;
  977. HdrType = AA_HEADER_TYPE_NONE;
  978. }
  979. AtmArpFreeSendPackets(
  980. pInterface,
  981. pPacketToBeQueued,
  982. HdrPresent
  983. );
  984. }
  985. }
  986. AADEBUGP(AAD_VERY_LOUD, ("Make Call: VC: 0x%x, returning status 0x%x\n",
  987. pVc, Status));
  988. return Status;
  989. }
  990. VOID
  991. AtmArpFillCallParameters(
  992. IN PCO_CALL_PARAMETERS pCallParameters,
  993. IN ULONG ParametersSize,
  994. IN PATM_ADDRESS pCalledAddress,
  995. IN PATM_ADDRESS pCallingAddress,
  996. IN PATMARP_FLOW_SPEC pFlowSpec,
  997. IN BOOLEAN IsPMP,
  998. IN BOOLEAN IsMakeCall
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Fill in a Call Parameters structure with the given information,
  1003. thus making it ready for use in an NdisClMakeCall/NdisClAddParty
  1004. call.
  1005. Arguments:
  1006. pCallParameters - points to structure to be filled in.
  1007. ParametersSize - size of the above
  1008. pCalledAddress - points to called ATM address
  1009. pCallingAddress - points to calling ATM address
  1010. pFlowSpec - points to Flow spec for this connection
  1011. IsPMP - Is this a point to multipoint connection?
  1012. IsMakeCall - Is this for MakeCall (FALSE => AddParty)
  1013. Return Value:
  1014. None
  1015. --*/
  1016. {
  1017. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  1018. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  1019. //
  1020. // All Info Elements that we need to fill:
  1021. //
  1022. Q2931_IE UNALIGNED * pIe;
  1023. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  1024. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  1025. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  1026. ATM_BLLI_IE UNALIGNED * pBlli;
  1027. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  1028. //
  1029. // Zero out everything. Don't remove this!
  1030. //
  1031. AA_SET_MEM((PUCHAR)pCallParameters, 0, ParametersSize);
  1032. //
  1033. // Distribute space amongst the various structures
  1034. //
  1035. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  1036. ((PUCHAR)pCallParameters +
  1037. sizeof(CO_CALL_PARAMETERS));
  1038. //
  1039. // Set pointers to link the above structures together
  1040. //
  1041. pCallParameters->CallMgrParameters = pCallMgrParameters;
  1042. pCallParameters->MediaParameters = (PCO_MEDIA_PARAMETERS)NULL;
  1043. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  1044. pCallMgrParameters->CallMgrSpecific.Length =
  1045. sizeof(Q2931_CALLMGR_PARAMETERS) +
  1046. (IsMakeCall? ATMARP_MAKE_CALL_IE_SPACE: ATMARP_ADD_PARTY_IE_SPACE);
  1047. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  1048. pCallMgrParameters->CallMgrSpecific.Parameters;
  1049. if (IsPMP)
  1050. {
  1051. pCallParameters->Flags |= MULTIPOINT_VC;
  1052. }
  1053. //
  1054. // Call Manager generic flow parameters:
  1055. //
  1056. pCallMgrParameters->Transmit.TokenRate = (pFlowSpec->SendAvgBandwidth);
  1057. pCallMgrParameters->Transmit.TokenBucketSize = (pFlowSpec->SendMaxSize);
  1058. pCallMgrParameters->Transmit.MaxSduSize = pFlowSpec->SendMaxSize;
  1059. pCallMgrParameters->Transmit.PeakBandwidth = (pFlowSpec->SendPeakBandwidth);
  1060. pCallMgrParameters->Transmit.ServiceType = pFlowSpec->SendServiceType;
  1061. if ((!IsPMP) && (IsMakeCall))
  1062. {
  1063. pCallMgrParameters->Receive.TokenRate = (pFlowSpec->ReceiveAvgBandwidth);
  1064. pCallMgrParameters->Receive.TokenBucketSize = pFlowSpec->ReceiveMaxSize;
  1065. pCallMgrParameters->Receive.MaxSduSize = pFlowSpec->ReceiveMaxSize;
  1066. pCallMgrParameters->Receive.PeakBandwidth = (pFlowSpec->ReceivePeakBandwidth);
  1067. pCallMgrParameters->Receive.ServiceType = pFlowSpec->ReceiveServiceType;
  1068. }
  1069. else
  1070. {
  1071. //
  1072. // else receive side values are 0's.
  1073. //
  1074. pCallMgrParameters->Receive.ServiceType = SERVICETYPE_NOTRAFFIC;
  1075. }
  1076. //
  1077. // Q2931 Call Manager Parameters:
  1078. //
  1079. //
  1080. // Called address:
  1081. //
  1082. // TBD: Add Called Subaddress IE in outgoing call.
  1083. //
  1084. AA_COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CalledParty),
  1085. (PUCHAR)pCalledAddress,
  1086. sizeof(ATM_ADDRESS));
  1087. //
  1088. // Calling address:
  1089. //
  1090. AA_COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CallingParty),
  1091. (PUCHAR)pCallingAddress,
  1092. sizeof(ATM_ADDRESS));
  1093. //
  1094. // RFC 1755 (Sec 5) says that the following IEs MUST be present in the
  1095. // SETUP message, so fill them all.
  1096. //
  1097. // AAL Parameters
  1098. // Traffic Descriptor (only for MakeCall)
  1099. // Broadband Bearer Capability (only for MakeCall)
  1100. // Broadband Low Layer Info
  1101. // QoS (only for MakeCall)
  1102. //
  1103. //
  1104. // Initialize the Info Element list
  1105. //
  1106. pAtmCallMgrParameters->InfoElementCount = 0;
  1107. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  1108. //
  1109. // AAL Parameters:
  1110. //
  1111. {
  1112. UNALIGNED AAL5_PARAMETERS *pAal5;
  1113. pIe->IEType = IE_AALParameters;
  1114. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  1115. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  1116. pAalIe->AALType = AAL_TYPE_AAL5;
  1117. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  1118. pAal5->ForwardMaxCPCSSDUSize = pFlowSpec->SendMaxSize;
  1119. pAal5->BackwardMaxCPCSSDUSize = pFlowSpec->ReceiveMaxSize;
  1120. }
  1121. pAtmCallMgrParameters->InfoElementCount++;
  1122. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1123. #ifdef PREPARE_IES_OURSELVES
  1124. //
  1125. // Let the Call Manager convert from generic flow spec to Traffic Descr,
  1126. // Broadband Bearer Cap, and QoS.
  1127. //
  1128. //
  1129. // Traffic Descriptor:
  1130. //
  1131. if (IsMakeCall)
  1132. {
  1133. pIe->IEType = IE_TrafficDescriptor;
  1134. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE;
  1135. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)pIe->IE;
  1136. if (pFlowSpec->SendServiceType == SERVICETYPE_BESTEFFORT)
  1137. {
  1138. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  1139. BYTES_TO_CELLS(pFlowSpec->SendPeakBandwidth);
  1140. if (!IsPMP)
  1141. {
  1142. pTrafficDescriptor->BackwardTD.PeakCellRateCLP01 =
  1143. BYTES_TO_CELLS(pFlowSpec->ReceivePeakBandwidth);
  1144. }
  1145. //
  1146. // else we have zero'ed out everything, which is what we want.
  1147. //
  1148. pTrafficDescriptor->BestEffort = TRUE;
  1149. }
  1150. else
  1151. {
  1152. // Predictive/Guaranteed service (we map this to CBR, see BBC below)
  1153. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  1154. BYTES_TO_CELLS(pFlowSpec->SendPeakBandwidth);
  1155. if (!IsPMP)
  1156. {
  1157. pTrafficDescriptor->BackwardTD.PeakCellRateCLP01 =
  1158. BYTES_TO_CELLS(pFlowSpec->ReceivePeakBandwidth);
  1159. }
  1160. //
  1161. // else we have zero'ed out everything, which is what we want.
  1162. //
  1163. pTrafficDescriptor->BestEffort = FALSE;
  1164. }
  1165. pAtmCallMgrParameters->InfoElementCount++;
  1166. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1167. }
  1168. //
  1169. // Broadband Bearer Capability
  1170. //
  1171. if (IsMakeCall)
  1172. {
  1173. pIe->IEType = IE_BroadbandBearerCapability;
  1174. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE;
  1175. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)pIe->IE;
  1176. pBbc->BearerClass = BCOB_X;
  1177. pBbc->UserPlaneConnectionConfig = (IsPMP ? UP_P2MP: UP_P2P);
  1178. if (pFlowSpec->SendServiceType == SERVICETYPE_BESTEFFORT)
  1179. {
  1180. pBbc->TrafficType = TT_NOIND;
  1181. pBbc->TimingRequirements = TR_NOIND;
  1182. pBbc->ClippingSusceptability = CLIP_NOT;
  1183. }
  1184. else
  1185. {
  1186. pBbc->TrafficType = TT_CBR;
  1187. pBbc->TimingRequirements = TR_END_TO_END;
  1188. pBbc->ClippingSusceptability = CLIP_SUS;
  1189. }
  1190. pAtmCallMgrParameters->InfoElementCount++;
  1191. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1192. }
  1193. #endif // PREPARE_IES_OURSELVES
  1194. //
  1195. // Broadband Lower Layer Information
  1196. //
  1197. pIe->IEType = IE_BLLI;
  1198. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  1199. pBlli = (PATM_BLLI_IE)pIe->IE;
  1200. AA_COPY_MEM((PUCHAR)pBlli,
  1201. (PUCHAR)&AtmArpDefaultBlli,
  1202. sizeof(ATM_BLLI_IE));
  1203. pAtmCallMgrParameters->InfoElementCount++;
  1204. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1205. #ifdef PREPARE_IES_OURSELVES
  1206. //
  1207. // QoS
  1208. //
  1209. if (IsMakeCall)
  1210. {
  1211. pIe->IEType = IE_QOSClass;
  1212. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE;
  1213. pQos = (PATM_QOS_CLASS_IE)pIe->IE;
  1214. if (pFlowSpec->SendServiceType == SERVICETYPE_BESTEFFORT)
  1215. {
  1216. pQos->QOSClassForward = pQos->QOSClassBackward = 0;
  1217. }
  1218. else
  1219. {
  1220. pQos->QOSClassForward = pQos->QOSClassBackward = 1;
  1221. }
  1222. pAtmCallMgrParameters->InfoElementCount++;
  1223. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1224. }
  1225. #endif // PREPARE_IES_OURSELVES
  1226. }
  1227. #ifdef IPMCAST
  1228. BOOLEAN
  1229. AtmArpMcPrepareAtmEntryForClose(
  1230. IN PATMARP_ATM_ENTRY pAtmEntry LOCKIN LOCKOUT
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. Prepare an ATM Entry that has an outgoing PMP call on it, for Close Call.
  1235. This means that we drop all but the last leaf on this PMP call.
  1236. NOTE: The caller is assumed to hold the ATM Entry lock
  1237. Arguments:
  1238. pAtmEntry - Points to ATM Entry representing a PMP call
  1239. Return Value:
  1240. TRUE iff the connection on this ATM Entry is ready for CloseCall.
  1241. --*/
  1242. {
  1243. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  1244. PATMARP_IPMC_ATM_ENTRY pNextMcAtmEntry;
  1245. PATMARP_INTERFACE pInterface;
  1246. NDIS_HANDLE NdisPartyHandle;
  1247. NDIS_STATUS Status;
  1248. AA_ASSERT(pAtmEntry->pMcAtmInfo->TransientLeaves == 0);
  1249. AA_ASSERT(pAtmEntry->pVcList != NULL_PATMARP_VC);
  1250. pInterface = pAtmEntry->pInterface;
  1251. AAMCDEBUGP(AAD_EXTRA_LOUD,
  1252. ("McPrepareAtmEntryForClose: pAtmEntry 0x%x, McList 0x%x, ActiveLeaves %d\n",
  1253. pAtmEntry,
  1254. pAtmEntry->pMcAtmInfo->pMcAtmEntryList,
  1255. pAtmEntry->pMcAtmInfo->ActiveLeaves));
  1256. //
  1257. // First, prune all members that aren't connected.
  1258. //
  1259. for (pMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1260. pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  1261. pMcAtmEntry = pNextMcAtmEntry)
  1262. {
  1263. pNextMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  1264. //
  1265. // Stop any timer running here.
  1266. //
  1267. (VOID)AtmArpStopTimer(&(pMcAtmEntry->Timer), pInterface);
  1268. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  1269. AA_IPMC_AE_CONN_STATE_MASK,
  1270. AA_IPMC_AE_CONN_DISCONNECTED))
  1271. {
  1272. AtmArpMcUnlinkAtmMember(
  1273. pAtmEntry,
  1274. pMcAtmEntry
  1275. );
  1276. }
  1277. }
  1278. //
  1279. // Next, send drop party requests for all but one member.
  1280. //
  1281. while (pAtmEntry->pMcAtmInfo->ActiveLeaves > 1)
  1282. {
  1283. for (pMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1284. /* NONE */;
  1285. pMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry)
  1286. {
  1287. AA_ASSERT(pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY);
  1288. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  1289. AA_IPMC_AE_CONN_STATE_MASK,
  1290. AA_IPMC_AE_CONN_ACTIVE))
  1291. {
  1292. break;
  1293. }
  1294. }
  1295. NdisPartyHandle = pMcAtmEntry->NdisPartyHandle;
  1296. AAMCDEBUGP(AAD_INFO,
  1297. ("PrepareAtmEntry: pAtmEntry 0x%x, will DropPty, McAtmEnt 0x%x, PtyHnd 0x%x\n",
  1298. pAtmEntry, pMcAtmEntry, NdisPartyHandle));
  1299. AA_SET_FLAG(pMcAtmEntry->Flags,
  1300. AA_IPMC_AE_CONN_STATE_MASK,
  1301. AA_IPMC_AE_CONN_WACK_DROP_PARTY);
  1302. pAtmEntry->pMcAtmInfo->ActiveLeaves--;
  1303. AA_RELEASE_AE_LOCK(pAtmEntry);
  1304. Status = NdisClDropParty(
  1305. NdisPartyHandle,
  1306. NULL, // Buffer
  1307. (UINT)0 // Size
  1308. );
  1309. if (Status != NDIS_STATUS_PENDING)
  1310. {
  1311. AtmArpDropPartyCompleteHandler(
  1312. Status,
  1313. (NDIS_HANDLE)pMcAtmEntry
  1314. );
  1315. }
  1316. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1317. }
  1318. //
  1319. // Now, if we have exactly one ATM member in the list of
  1320. // leaves for this PMP, we can CloseCall.
  1321. //
  1322. if (pAtmEntry->pMcAtmInfo->pMcAtmEntryList->pNextMcAtmEntry ==
  1323. NULL_PATMARP_IPMC_ATM_ENTRY)
  1324. {
  1325. return (TRUE);
  1326. }
  1327. else
  1328. {
  1329. return (FALSE);
  1330. }
  1331. }
  1332. #endif // IPMCAST
  1333. VOID
  1334. AtmArpCloseCall(
  1335. IN PATMARP_VC pVc LOCKIN NOLOCKOUT
  1336. )
  1337. /*++
  1338. Routine Description:
  1339. Closes an existing call on a VC. It is assumed that a call exists
  1340. on the VC.
  1341. NOTE: The caller is assumed to hold a lock to the VC structure,
  1342. and it will be released here.
  1343. SIDE EFFECT: If the NDIS call returns other than NDIS_STATUS_PENDING,
  1344. we call our CloseCall Complete handler from here.
  1345. Arguments:
  1346. pVc - Pointer to ATMARP VC structure.
  1347. Return Value:
  1348. None
  1349. --*/
  1350. {
  1351. PATMARP_INTERFACE pInterface;
  1352. PATMARP_ATM_ENTRY pAtmEntry;
  1353. NDIS_HANDLE NdisVcHandle;
  1354. NDIS_HANDLE ProtocolVcContext;
  1355. #ifdef IPMCAST
  1356. NDIS_HANDLE NdisPartyHandle;
  1357. #endif
  1358. NDIS_STATUS Status;
  1359. PNDIS_PACKET PacketList; // Packets queued on this VC
  1360. AA_HEADER_TYPE HdrType; // for queued packets
  1361. BOOLEAN HdrPresent; // for queued packets
  1362. BOOLEAN WasRunning; // Was a timer running on this VC?
  1363. BOOLEAN IsPMP; // Is this a PMP call?
  1364. ULONG rc; // Ref Count on this VC.
  1365. AA_STRUCT_ASSERT(pVc, avc);
  1366. NdisVcHandle = pVc->NdisVcHandle;
  1367. ProtocolVcContext = (NDIS_HANDLE)pVc;
  1368. pInterface = pVc->pInterface;
  1369. IsPMP = AA_IS_FLAG_SET(pVc->Flags,
  1370. AA_VC_CONN_TYPE_MASK,
  1371. AA_VC_CONN_TYPE_PMP);
  1372. AADEBUGP(AAD_INFO,
  1373. ("Closing call on VC 0x%x, VC Flags 0x%x, Ref %d, NdisVcHandle 0x%x\n",
  1374. pVc, pVc->Flags, pVc->RefCount, NdisVcHandle));
  1375. //
  1376. // Remove the list of packets queued on this VC.
  1377. //
  1378. PacketList = pVc->PacketList;
  1379. pVc->PacketList = (PNDIS_PACKET)NULL;
  1380. if (pVc->FlowSpec.Encapsulation == ENCAPSULATION_TYPE_LLCSNAP)
  1381. {
  1382. HdrType = (IsPMP ? AA_HEADER_TYPE_NUNICAST: AA_HEADER_TYPE_UNICAST);
  1383. HdrPresent = TRUE;
  1384. }
  1385. else
  1386. {
  1387. HdrType = AA_HEADER_TYPE_NONE;
  1388. HdrPresent = FALSE;
  1389. }
  1390. //
  1391. // Stop any timer running on this VC.
  1392. //
  1393. WasRunning = AtmArpStopTimer(&(pVc->Timer), pInterface);
  1394. if (WasRunning)
  1395. {
  1396. //
  1397. // Remove the timer reference on this VC.
  1398. //
  1399. rc = AtmArpDereferenceVc(pVc);
  1400. }
  1401. else
  1402. {
  1403. rc = pVc->RefCount;
  1404. }
  1405. #ifdef GPC
  1406. //
  1407. // If this VC is associated with a Flow, unlink them.
  1408. //
  1409. if (rc != 0)
  1410. {
  1411. if (pVc->FlowHandle != NULL)
  1412. {
  1413. PATMARP_FLOW_INFO pFlowInfo = (PATMARP_FLOW_INFO)pVc->FlowHandle;
  1414. if ((PVOID)pVc == InterlockedCompareExchangePointer(
  1415. &(pFlowInfo->VcContext),
  1416. NULL,
  1417. pVc
  1418. ))
  1419. {
  1420. pVc->FlowHandle = NULL;
  1421. rc = AtmArpDereferenceVc(pVc); // Unlink from GPC Flow
  1422. }
  1423. }
  1424. }
  1425. #endif // GPC
  1426. if (rc != 0)
  1427. {
  1428. //
  1429. // Check the call state on this VC. If the call is active and
  1430. // we have no sends going on, then we close the call.
  1431. // Otherwise, simply mark the VC as closing. We will continue
  1432. // this process when the current operation on the VC completes.
  1433. //
  1434. if (AA_IS_FLAG_SET(pVc->Flags,
  1435. AA_VC_CALL_STATE_MASK,
  1436. AA_VC_CALL_STATE_ACTIVE) &&
  1437. (pVc->OutstandingSends == 0))
  1438. {
  1439. //
  1440. // Set VC call state to "Close Call in progress" so that we don't
  1441. // reenter here.
  1442. //
  1443. AA_SET_FLAG(
  1444. pVc->Flags,
  1445. AA_VC_CALL_STATE_MASK,
  1446. AA_VC_CALL_STATE_CLOSE_IN_PROGRESS);
  1447. #ifdef IPMCAST
  1448. if (IsPMP)
  1449. {
  1450. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry; // last leaf
  1451. pAtmEntry = pVc->pAtmEntry;
  1452. AA_ASSERT(pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  1453. AA_ASSERT(pAtmEntry->pMcAtmInfo != NULL_PATMARP_IPMC_ATM_INFO);
  1454. if (pAtmEntry->pMcAtmInfo->TransientLeaves == 0)
  1455. {
  1456. //
  1457. // No AddParty in progress.
  1458. //
  1459. AA_RELEASE_VC_LOCK(pVc);
  1460. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1461. if (AtmArpMcPrepareAtmEntryForClose(pAtmEntry))
  1462. {
  1463. //
  1464. // The entry is ready for CloseCall.
  1465. //
  1466. AAMCDEBUGP(AAD_LOUD,
  1467. ("CloseCall (MC): pAtmEntry 0x%x, ready for close\n", pAtmEntry));
  1468. //
  1469. // Get the party handle of the last leaf, and unlink
  1470. // it from the PMP structure.
  1471. //
  1472. AA_ASSERT(pAtmEntry->pMcAtmInfo->pMcAtmEntryList !=
  1473. NULL_PATMARP_IPMC_ATM_ENTRY);
  1474. pMcAtmEntry = pVc->pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
  1475. NdisPartyHandle = pMcAtmEntry->NdisPartyHandle;
  1476. AA_SET_FLAG(pMcAtmEntry->Flags,
  1477. AA_IPMC_AE_CONN_STATE_MASK,
  1478. AA_IPMC_AE_CONN_WACK_DROP_PARTY);
  1479. pAtmEntry->pMcAtmInfo->ActiveLeaves--;
  1480. AA_ASSERT(pAtmEntry->pMcAtmInfo->ActiveLeaves == 0);
  1481. AA_RELEASE_AE_LOCK(pAtmEntry);
  1482. AA_ACQUIRE_VC_LOCK(pVc);
  1483. }
  1484. else
  1485. {
  1486. AA_RELEASE_AE_LOCK(pAtmEntry);
  1487. AA_ACQUIRE_VC_LOCK(pVc);
  1488. //
  1489. // There are pending DropParty calls. Mark this VC
  1490. // so that we trigger a CloseCall when all DropParty
  1491. // calls complete.
  1492. //
  1493. AA_SET_FLAG(pVc->Flags,
  1494. AA_VC_CLOSE_STATE_MASK,
  1495. AA_VC_CLOSE_STATE_CLOSING);
  1496. NdisVcHandle = NULL; // Don't close call now
  1497. }
  1498. }
  1499. else
  1500. {
  1501. //
  1502. // There are pending AddParty calls. Mark this VC
  1503. // so that we trigger a CloseCall when all AddParty
  1504. // calls complete.
  1505. //
  1506. AA_SET_FLAG(pVc->Flags,
  1507. AA_VC_CLOSE_STATE_MASK,
  1508. AA_VC_CLOSE_STATE_CLOSING);
  1509. NdisVcHandle = NULL; // Don't close call now
  1510. }
  1511. }
  1512. else
  1513. {
  1514. NdisPartyHandle = NULL;
  1515. }
  1516. if (NdisVcHandle != NULL)
  1517. {
  1518. AA_RELEASE_VC_LOCK(pVc);
  1519. Status = NdisClCloseCall(
  1520. NdisVcHandle,
  1521. NdisPartyHandle,
  1522. (PVOID)NULL, // No Buffer
  1523. (UINT)0 // Size of above
  1524. );
  1525. if (Status != NDIS_STATUS_PENDING)
  1526. {
  1527. AtmArpCloseCallCompleteHandler(
  1528. Status,
  1529. ProtocolVcContext,
  1530. (NDIS_HANDLE)NULL
  1531. );
  1532. }
  1533. }
  1534. else
  1535. {
  1536. //
  1537. // Set the call state back to what it was.
  1538. //
  1539. AA_SET_FLAG(
  1540. pVc->Flags,
  1541. AA_VC_CALL_STATE_MASK,
  1542. AA_VC_CALL_STATE_ACTIVE);
  1543. AA_RELEASE_VC_LOCK(pVc);
  1544. }
  1545. #else
  1546. AA_RELEASE_VC_LOCK(pVc);
  1547. Status = NdisClCloseCall(
  1548. NdisVcHandle,
  1549. NULL, // NdisPartyHandle
  1550. (PVOID)NULL, // No Buffer
  1551. (UINT)0 // Size of above
  1552. );
  1553. if (Status != NDIS_STATUS_PENDING)
  1554. {
  1555. AtmArpCloseCallCompleteHandler(
  1556. Status,
  1557. ProtocolVcContext,
  1558. (NDIS_HANDLE)NULL
  1559. );
  1560. }
  1561. #endif // IPMCAST
  1562. }
  1563. else
  1564. {
  1565. //
  1566. // Some operation is going on here (call setup/close/send). Mark this
  1567. // VC so that we know what to do when this operation completes.
  1568. //
  1569. AA_SET_FLAG(
  1570. pVc->Flags,
  1571. AA_VC_CLOSE_STATE_MASK,
  1572. AA_VC_CLOSE_STATE_CLOSING);
  1573. AA_RELEASE_VC_LOCK(pVc);
  1574. }
  1575. }
  1576. //
  1577. // else the VC is gone.
  1578. //
  1579. //
  1580. // Free any packets queued on this VC
  1581. //
  1582. if (PacketList != (PNDIS_PACKET)NULL)
  1583. {
  1584. AtmArpFreeSendPackets(
  1585. pInterface,
  1586. PacketList,
  1587. HdrPresent
  1588. );
  1589. }
  1590. }
  1591. NDIS_STATUS
  1592. AtmArpCreateVcHandler(
  1593. IN NDIS_HANDLE ProtocolAfContext,
  1594. IN NDIS_HANDLE NdisVcHandle,
  1595. OUT PNDIS_HANDLE pProtocolVcContext
  1596. )
  1597. /*++
  1598. Routine Description:
  1599. Entry point called by NDIS when the Call Manager wants to create
  1600. a new endpoint (VC). We allocate a new ATMARP VC structure, and
  1601. return a pointer to it as our VC context.
  1602. Arguments:
  1603. ProtocolAfContext - Actually a pointer to the ATMARP Interface structure
  1604. NdisVcHandle - Handle for this VC for all future references
  1605. pProtocolVcContext - Place where we (protocol) return our context for the VC
  1606. Return Value:
  1607. NDIS_STATUS_SUCCESS if we could create a VC
  1608. NDIS_STATUS_RESOURCES otherwise
  1609. --*/
  1610. {
  1611. PATMARP_INTERFACE pInterface;
  1612. PATMARP_VC pVc;
  1613. NDIS_STATUS Status;
  1614. pInterface = (PATMARP_INTERFACE)ProtocolAfContext;
  1615. pVc = AtmArpAllocateVc(pInterface);
  1616. if (pVc != NULL_PATMARP_VC)
  1617. {
  1618. *pProtocolVcContext = (NDIS_HANDLE)pVc;
  1619. pVc->NdisVcHandle = NdisVcHandle;
  1620. pVc->Flags = AA_VC_OWNER_IS_CALLMGR;
  1621. AtmArpReferenceVc(pVc); // Create VC ref
  1622. Status = NDIS_STATUS_SUCCESS;
  1623. }
  1624. else
  1625. {
  1626. Status = NDIS_STATUS_RESOURCES;
  1627. }
  1628. AADEBUGP(AAD_INFO, ("Create Vc Handler: pVc 0x%x, Status 0x%x\n", pVc, Status));
  1629. return (Status);
  1630. }
  1631. NDIS_STATUS
  1632. AtmArpDeleteVcHandler(
  1633. IN NDIS_HANDLE ProtocolVcContext
  1634. )
  1635. /*++
  1636. Routine Description:
  1637. Our Delete VC handler. This VC would have been allocated as a result
  1638. of a previous entry into our CreateVcHandler, and possibly used for
  1639. an incoming call.
  1640. At this time, this VC structure should be free of any calls, and we
  1641. simply free this.
  1642. Arguments:
  1643. ProtocolVcContext - pointer to our VC structure
  1644. Return Value:
  1645. NDIS_STATUS_SUCCESS always
  1646. --*/
  1647. {
  1648. PATMARP_VC pVc;
  1649. ULONG rc; // Ref count on the VC
  1650. pVc = (PATMARP_VC)ProtocolVcContext;
  1651. AA_STRUCT_ASSERT(pVc, avc);
  1652. AA_ASSERT((pVc->Flags & AA_VC_OWNER_MASK) == AA_VC_OWNER_IS_CALLMGR);
  1653. AA_ACQUIRE_VC_LOCK(pVc);
  1654. rc = AtmArpDereferenceVc(pVc);
  1655. if (rc > 0)
  1656. {
  1657. //
  1658. // This can happen if there is a timer still running
  1659. // on this VC. When the timer elapses, the VC will be
  1660. // freed.
  1661. //
  1662. AADEBUGP(AAD_WARNING, ("Delete VC handler: pVc 0x%x, Flags 0x%x, refcount %d, pAtmEntry %x\n",
  1663. pVc, pVc->Flags, rc, pVc->pAtmEntry));
  1664. AA_RELEASE_VC_LOCK(pVc);
  1665. }
  1666. //
  1667. // else the VC is gone.
  1668. //
  1669. AADEBUGP(AAD_LOUD, ("Delete Vc Handler: 0x%x: done\n", pVc));
  1670. return (NDIS_STATUS_SUCCESS);
  1671. }
  1672. NDIS_STATUS
  1673. AtmArpIncomingCallHandler(
  1674. IN NDIS_HANDLE ProtocolSapContext,
  1675. IN NDIS_HANDLE ProtocolVcContext,
  1676. IN OUT PCO_CALL_PARAMETERS pCallParameters
  1677. )
  1678. /*++
  1679. Routine Description:
  1680. This handler is called when there is an incoming call matching our
  1681. SAP. This could be either an SVC or a PVC. In either case, we store
  1682. FlowSpec information from the incoming call in the VC structure, making
  1683. sure that the MTU for the interface is not violated.
  1684. For an SVC, we expect a Calling Address to be present in the call,
  1685. otherwise we reject the call. If an ATM Entry with this address exists,
  1686. this VC is linked to that entry, otherwise a new entry with this address
  1687. is created.
  1688. In the case of a PVC, we ignore any Calling Address information, and
  1689. depend on InATMARP to resolve the ATM Address as well as the IP address
  1690. of the other end.
  1691. Arguments:
  1692. ProtocolSapContext - Pointer to ATMARP Interface structure
  1693. ProtocolVcContext - Pointer to ATMARP VC structure
  1694. pCallParameters - Call parameters
  1695. Return Value:
  1696. NDIS_STATUS_SUCCESS if we accept this call
  1697. NDIS_STATUS_FAILURE if we reject it.
  1698. --*/
  1699. {
  1700. PATMARP_VC pVc;
  1701. PATMARP_ATM_ENTRY pAtmEntry;
  1702. PATMARP_INTERFACE pInterface;
  1703. CO_CALL_MANAGER_PARAMETERS UNALIGNED * pCallMgrParameters;
  1704. Q2931_CALLMGR_PARAMETERS UNALIGNED * pAtmCallMgrParameters;
  1705. //
  1706. // To traverse the list of Info Elements
  1707. //
  1708. Q2931_IE UNALIGNED * pIe;
  1709. ULONG InfoElementCount;
  1710. //
  1711. // Info Elements in the incoming call, that are of interest to us.
  1712. // Initialize these to <not present>.
  1713. //
  1714. ATM_ADDRESS UNALIGNED * pCallingAddress = NULL;
  1715. ATM_CALLING_PARTY_SUBADDRESS_IE UNALIGNED * pCallingSubaddressIe = NULL;
  1716. ATM_ADDRESS UNALIGNED * pCallingSubaddress = NULL;
  1717. AAL_PARAMETERS_IE UNALIGNED * pAal = NULL;
  1718. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor = NULL;
  1719. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc = NULL;
  1720. ATM_BLLI_IE UNALIGNED * pBlli = NULL;
  1721. ATM_QOS_CLASS_IE UNALIGNED * pQos = NULL;
  1722. AAL5_PARAMETERS UNALIGNED * pAal5;
  1723. UCHAR AddrTypeLen;
  1724. UCHAR SubaddrTypeLen;
  1725. PUCHAR pAtmSubaddress;
  1726. NDIS_STATUS Status;
  1727. pVc = (PATMARP_VC)ProtocolVcContext;
  1728. AA_STRUCT_ASSERT(pVc, avc);
  1729. AA_ASSERT((pVc->Flags & AA_VC_TYPE_MASK) == AA_VC_TYPE_UNUSED);
  1730. AA_ASSERT((pVc->Flags & AA_VC_OWNER_MASK) == AA_VC_OWNER_IS_CALLMGR);
  1731. AA_ASSERT((pVc->Flags & AA_VC_CALL_STATE_MASK) == AA_VC_CALL_STATE_IDLE);
  1732. pInterface = pVc->pInterface;
  1733. AADEBUGP(AAD_LOUD, ("Incoming Call: IF 0x%x, VC 0x%x, pCallParams 0x%x\n",
  1734. pInterface, pVc, pCallParameters));
  1735. do
  1736. {
  1737. if (pInterface->AdminState != IF_STATUS_UP)
  1738. {
  1739. Status = NDIS_STATUS_FAILURE;
  1740. break;
  1741. }
  1742. //
  1743. // Get the following info from the Incoming call:
  1744. // Calling Address
  1745. // AAL Parameters
  1746. // Traffic Descriptor
  1747. // Broadband Bearer Capability
  1748. // QoS
  1749. //
  1750. pCallMgrParameters = pCallParameters->CallMgrParameters;
  1751. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  1752. pCallParameters->CallMgrParameters->CallMgrSpecific.Parameters;
  1753. pCallingAddress = &(pAtmCallMgrParameters->CallingParty);
  1754. InfoElementCount = pAtmCallMgrParameters->InfoElementCount;
  1755. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  1756. while (InfoElementCount--)
  1757. {
  1758. switch (pIe->IEType)
  1759. {
  1760. case IE_AALParameters:
  1761. pAal = (PAAL_PARAMETERS_IE)(pIe->IE);
  1762. break;
  1763. case IE_TrafficDescriptor:
  1764. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)(pIe->IE);
  1765. break;
  1766. case IE_BroadbandBearerCapability:
  1767. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)(pIe->IE);
  1768. break;
  1769. case IE_QOSClass:
  1770. pQos = (PATM_QOS_CLASS_IE)(pIe->IE);
  1771. break;
  1772. case IE_CallingPartySubaddress:
  1773. pCallingSubaddressIe = (ATM_CALLING_PARTY_SUBADDRESS_IE *)(pIe->IE);
  1774. pCallingSubaddress = pCallingSubaddressIe;
  1775. break;
  1776. default:
  1777. break;
  1778. }
  1779. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1780. }
  1781. if ((pCallParameters->Flags & PERMANENT_VC) == 0)
  1782. {
  1783. //
  1784. // This is an SVC.
  1785. //
  1786. //
  1787. // Make sure all mandatory IEs are present. If not, reject the call
  1788. //
  1789. if ((pAal == (PAAL_PARAMETERS_IE)NULL) ||
  1790. (pTrafficDescriptor == (PATM_TRAFFIC_DESCRIPTOR_IE)NULL) ||
  1791. (pBbc == (PATM_BROADBAND_BEARER_CAPABILITY_IE)NULL) ||
  1792. (pQos == (PATM_QOS_CLASS_IE)NULL))
  1793. {
  1794. AADEBUGP(AAD_WARNING,
  1795. ("In call: IE missing: AAL 0x%x, TRAF 0x%x, BBC 0x%x, QOS 0x%x",
  1796. pAal,
  1797. pTrafficDescriptor,
  1798. pBbc,
  1799. pQos));
  1800. Status = NDIS_STATUS_AAL_PARAMS_UNSUPPORTED;
  1801. break;
  1802. }
  1803. //
  1804. // We insist on the Calling Address
  1805. // being present, as well
  1806. //
  1807. if (pCallingAddress->NumberOfDigits == 0)
  1808. {
  1809. AADEBUGP(AAD_WARNING, ("In call: calling address missing for SVC\n"));
  1810. Status = NDIS_STATUS_INVALID_ADDRESS;
  1811. break;
  1812. }
  1813. }
  1814. if (pAal != NULL)
  1815. {
  1816. //
  1817. // Make sure that the requested MTU values aren't beyond our
  1818. // capabilities:
  1819. //
  1820. pAal5 = &(pAal->AALSpecificParameters.AAL5Parameters);
  1821. if (pAal5->ForwardMaxCPCSSDUSize > pInterface->pAdapter->MaxPacketSize)
  1822. {
  1823. pAal5->ForwardMaxCPCSSDUSize = pInterface->pAdapter->MaxPacketSize;
  1824. }
  1825. if (pAal5->BackwardMaxCPCSSDUSize > pInterface->pAdapter->MaxPacketSize)
  1826. {
  1827. pAal5->BackwardMaxCPCSSDUSize = pInterface->pAdapter->MaxPacketSize;
  1828. }
  1829. }
  1830. #ifdef PREPARE_IES_OURSELVES
  1831. //
  1832. // Get the Flow Specs for this VC from the ATM Info Elements
  1833. //
  1834. pVc->FlowSpec.SendPeakBandwidth =
  1835. CELLS_TO_BYTES(pTrafficDescriptor->ForwardTD.PeakCellRateCLP01);
  1836. pVc->FlowSpec.SendMaxSize = pAal5->ForwardMaxCPCSSDUSize;
  1837. pVc->FlowSpec.ReceivePeakBandwidth =
  1838. CELLS_TO_BYTES(pTrafficDescriptor->BackwardTD.PeakCellRateCLP01);
  1839. pVc->FlowSpec.ReceiveMaxSize = pAal5->BackwardMaxCPCSSDUSize;
  1840. if ((pQos->QOSClassForward == 0) || (pQos->QOSClassBackward == 0))
  1841. {
  1842. pVc->FlowSpec.SendServiceType = SERVICETYPE_BESTEFFORT;
  1843. }
  1844. else
  1845. {
  1846. pVc->FlowSpec.SendServiceType = SERVICETYPE_GUARANTEED;
  1847. }
  1848. #else
  1849. //
  1850. // Get the Flow Specs for this VC
  1851. //
  1852. pVc->FlowSpec.SendPeakBandwidth = pCallMgrParameters->Transmit.PeakBandwidth;
  1853. pVc->FlowSpec.SendAvgBandwidth = pCallMgrParameters->Transmit.TokenRate;
  1854. pVc->FlowSpec.SendMaxSize = pCallMgrParameters->Transmit.MaxSduSize;
  1855. pVc->FlowSpec.SendServiceType = pCallMgrParameters->Transmit.ServiceType;
  1856. pVc->FlowSpec.ReceivePeakBandwidth = pCallMgrParameters->Receive.PeakBandwidth;
  1857. pVc->FlowSpec.ReceiveAvgBandwidth = pCallMgrParameters->Receive.TokenRate;
  1858. pVc->FlowSpec.ReceiveMaxSize = pCallMgrParameters->Receive.MaxSduSize;
  1859. pVc->FlowSpec.ReceiveServiceType = pCallMgrParameters->Receive.ServiceType;
  1860. #endif // PREPARE_IES_OURSELVES
  1861. AADEBUGP(AAD_LOUD, ("InCall: VC 0x%x: Type %s, Calling Addr:\n",
  1862. pVc,
  1863. (((pCallParameters->Flags & PERMANENT_VC) == 0)? "SVC": "PVC")
  1864. ));
  1865. AADEBUGPDUMP(AAD_LOUD, pCallingAddress->Address, pCallingAddress->NumberOfDigits);
  1866. AADEBUGP(AAD_LOUD,
  1867. ("InCall: VC 0x%x: SendBW: %d, RcvBW: %d, SendSz %d, RcvSz %d\n",
  1868. pVc,
  1869. pVc->FlowSpec.SendPeakBandwidth,
  1870. pVc->FlowSpec.ReceivePeakBandwidth,
  1871. pVc->FlowSpec.SendMaxSize,
  1872. pVc->FlowSpec.ReceiveMaxSize));
  1873. #if DBG
  1874. if (pCallParameters->Flags & MULTIPOINT_VC)
  1875. {
  1876. AAMCDEBUGPATMADDR(AAD_EXTRA_LOUD, "Incoming PMP call from :", pCallingAddress);
  1877. }
  1878. #endif // DBG
  1879. //
  1880. // If this is a PVC, we are done. Accept the call.
  1881. //
  1882. if ((pCallParameters->Flags & PERMANENT_VC) != 0)
  1883. {
  1884. pVc->Flags |= (AA_VC_TYPE_PVC|AA_VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1885. Status = NDIS_STATUS_SUCCESS;
  1886. break;
  1887. }
  1888. //
  1889. // Here if SVC. Check if an ATM Entry for this Calling address exists.
  1890. // If an entry exists, link this VC to the entry; otherwise, create a new
  1891. // ATM entry and link this VC to it.
  1892. //
  1893. AddrTypeLen = AA_PKT_ATM_ADDRESS_TO_TYPE_LEN(pCallingAddress);
  1894. if (pCallingSubaddress != (PATM_ADDRESS)NULL)
  1895. {
  1896. SubaddrTypeLen = AA_PKT_ATM_ADDRESS_TO_TYPE_LEN(pCallingSubaddress);
  1897. pAtmSubaddress = pCallingSubaddress->Address;
  1898. }
  1899. else
  1900. {
  1901. SubaddrTypeLen = 0;
  1902. pAtmSubaddress = (PUCHAR)NULL;
  1903. }
  1904. pAtmEntry = AtmArpSearchForAtmAddress(
  1905. pInterface,
  1906. AddrTypeLen,
  1907. pCallingAddress->Address,
  1908. SubaddrTypeLen,
  1909. pAtmSubaddress,
  1910. AE_REFTYPE_TMP,
  1911. TRUE // Create one if no match found
  1912. );
  1913. if (pAtmEntry == NULL_PATMARP_ATM_ENTRY)
  1914. {
  1915. Status = NDIS_STATUS_FAILURE;
  1916. break;
  1917. }
  1918. //
  1919. // Link this VC to the ATM Entry, and accept this call.
  1920. //
  1921. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1922. {
  1923. ULONG rc;
  1924. AtmArpLinkVcToAtmEntry(pVc, pAtmEntry);
  1925. //
  1926. // AtmArpSearchForAtmAddress addrefd pAtmEntry for us -- we deref it
  1927. // here (AFTER calling AtmArpLinkVcToAtmEntry).
  1928. //
  1929. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP);
  1930. if (rc == 0)
  1931. {
  1932. //
  1933. // We shouldn't get here because AtmArpLinkVcToAtmEntry
  1934. // should have added a reference tp pAtmEntry.
  1935. //
  1936. AA_ASSERT(FALSE);
  1937. Status = NDIS_STATUS_FAILURE;
  1938. break;
  1939. }
  1940. }
  1941. AA_RELEASE_AE_LOCK(pAtmEntry);
  1942. //
  1943. // All checks for an incoming SVC are complete.
  1944. //
  1945. pVc->Flags |= (AA_VC_TYPE_SVC|AA_VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1946. AtmArpReferenceVc(pVc); // ATM Entry reference
  1947. Status = NDIS_STATUS_SUCCESS;
  1948. break;
  1949. }
  1950. while (FALSE);
  1951. AADEBUGP(AAD_VERY_LOUD, ("Incoming call: VC 0x%x, Status 0x%x\n", pVc, Status));
  1952. return Status;
  1953. }
  1954. VOID
  1955. AtmArpCallConnectedHandler(
  1956. IN NDIS_HANDLE ProtocolVcContext
  1957. )
  1958. /*++
  1959. Routine Description:
  1960. This handler is called as the final step in an incoming call, to inform
  1961. us that the call is fully setup.
  1962. For a PVC, we link the ATMARP VC structure in the list of unresolved PVCs,
  1963. and use InATMARP to resolve both the IP and ATM addresses of the other
  1964. end.
  1965. For an SVC, we send off any packets queued on the VC while we were waiting
  1966. for the Call Connected.
  1967. Arguments:
  1968. ProtocolVcContext - Pointer to ATMARP VC structure
  1969. Return Value:
  1970. None
  1971. --*/
  1972. {
  1973. PATMARP_VC pVc;
  1974. PATMARP_INTERFACE pInterface;
  1975. #if DBG
  1976. AA_IRQL EntryIrq, ExitIrq;
  1977. #endif
  1978. AA_GET_ENTRY_IRQL(EntryIrq);
  1979. pVc = (PATMARP_VC)ProtocolVcContext;
  1980. AA_STRUCT_ASSERT(pVc, avc);
  1981. AA_ASSERT((pVc->Flags & AA_VC_CALL_STATE_MASK)
  1982. == AA_VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1983. AA_ACQUIRE_VC_LOCK(pVc);
  1984. //
  1985. // Note down that a call is active on this VC.
  1986. //
  1987. AA_SET_FLAG(
  1988. pVc->Flags,
  1989. AA_VC_CALL_STATE_MASK,
  1990. AA_VC_CALL_STATE_ACTIVE
  1991. );
  1992. AtmArpReferenceVc(pVc); // Incoming call reference
  1993. AADEBUGP(AAD_INFO, ("Call Connected: VC: 0x%x, Flags: 0x%x, ATM Entry: 0x%x\n",
  1994. pVc, pVc->Flags, pVc->pAtmEntry));
  1995. pInterface = pVc->pInterface;
  1996. AA_STRUCT_ASSERT(pInterface, aai);
  1997. if (pInterface->AdminState == IF_STATUS_UP)
  1998. {
  1999. if ((pVc->Flags & AA_VC_TYPE_PVC) != 0)
  2000. {
  2001. //
  2002. // This is a PVC, link it to the list of unresolved PVCs, and
  2003. // send an InATMARP request on it.
  2004. //
  2005. pVc->pNextVc = pInterface->pUnresolvedVcs;
  2006. pInterface->pUnresolvedVcs = pVc;
  2007. AA_SET_FLAG(pVc->Flags,
  2008. AA_VC_ARP_STATE_MASK,
  2009. AA_VC_INARP_IN_PROGRESS);
  2010. //
  2011. // Start an InARP wait timer while we hold a lock for
  2012. // the Interface
  2013. //
  2014. AtmArpStartTimer(
  2015. pInterface,
  2016. &(pVc->Timer),
  2017. AtmArpPVCInARPWaitTimeout,
  2018. pInterface->InARPWaitTimeout,
  2019. (PVOID)pVc
  2020. );
  2021. AtmArpReferenceVc(pVc); // Timer ref
  2022. AtmArpReferenceVc(pVc); // Unresolved VCs Link reference
  2023. AADEBUGP(AAD_LOUD, ("PVC Call Connected: VC 0x%x\n", pVc));
  2024. #ifndef VC_REFS_ON_SENDS
  2025. AA_RELEASE_VC_LOCK(pVc);
  2026. #endif // VC_REFS_ON_SENDS
  2027. AtmArpSendInARPRequest(pVc);
  2028. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  2029. }
  2030. else
  2031. {
  2032. AADEBUGP(AAD_LOUD, ("SVC Call Connected: VC 0x%x\n", pVc));
  2033. AtmArpStartSendsOnVc(pVc);
  2034. //
  2035. // The VC lock is released within StartSendsOnVc()
  2036. //
  2037. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  2038. }
  2039. }
  2040. else
  2041. {
  2042. //
  2043. // The interface is marked as down. Close this call.
  2044. //
  2045. AtmArpCloseCall(pVc);
  2046. //
  2047. // The VC lock is released within the above
  2048. //
  2049. }
  2050. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  2051. return;
  2052. }
  2053. VOID
  2054. AtmArpIncomingCloseHandler(
  2055. IN NDIS_STATUS CloseStatus,
  2056. IN NDIS_HANDLE ProtocolVcContext,
  2057. IN PVOID pCloseData OPTIONAL,
  2058. IN UINT Size OPTIONAL
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. This handler is called when a call is closed, either by the network
  2063. or by the remote peer.
  2064. Arguments:
  2065. CloseStatus - Reason for the call clearing
  2066. ProtocolVcContext - Actually a pointer to the ATMARP VC structure
  2067. pCloseData - Additional info about the close
  2068. Size - Length of above
  2069. Return Value:
  2070. None
  2071. --*/
  2072. {
  2073. PATMARP_VC pVc;
  2074. PATMARP_ATM_ENTRY pAtmEntry;
  2075. PATMARP_INTERFACE pInterface;
  2076. ULONG rc; // Ref Count
  2077. BOOLEAN VcAbnormalTermination;
  2078. BOOLEAN IsPVC;
  2079. BOOLEAN Found;
  2080. PATM_CAUSE_IE pCauseIe;
  2081. pVc = (PATMARP_VC)ProtocolVcContext;
  2082. AA_STRUCT_ASSERT(pVc, avc);
  2083. AADEBUGP(AAD_INFO, ("Incoming Close: pVc 0x%x, Status 0x%x\n", pVc, CloseStatus));
  2084. pCauseIe = (PATM_CAUSE_IE)pCloseData;
  2085. #if DBG
  2086. if (pCauseIe != (PATM_CAUSE_IE)NULL)
  2087. {
  2088. AADEBUGP(AAD_INFO, ("Incoming Close: pVc 0x%x, Locn 0x%x, Cause 0x%x\n",
  2089. pVc, pCauseIe->Location, pCauseIe->Cause));
  2090. }
  2091. #endif // DBG
  2092. AA_ACQUIRE_VC_LOCK(pVc);
  2093. IsPVC = AA_IS_FLAG_SET(pVc->Flags, AA_VC_TYPE_MASK, AA_VC_TYPE_PVC);
  2094. pInterface = pVc->pInterface;
  2095. //
  2096. // Stop any timer (e.g. VC aging) running on this VC
  2097. //
  2098. if (AtmArpStopTimer(&(pVc->Timer), pVc->pInterface))
  2099. {
  2100. //
  2101. // A timer WAS running
  2102. //
  2103. rc = AtmArpDereferenceVc(pVc); // Timer reference
  2104. AA_ASSERT(rc > 0);
  2105. }
  2106. if ((CloseStatus == NDIS_STATUS_DEST_OUT_OF_ORDER) || IsPVC)
  2107. {
  2108. //
  2109. // This is an abnormal close, note down the fact
  2110. //
  2111. VcAbnormalTermination = TRUE;
  2112. }
  2113. else
  2114. {
  2115. VcAbnormalTermination = FALSE;
  2116. }
  2117. if (AA_IS_FLAG_SET(pVc->Flags,
  2118. AA_VC_CALL_STATE_MASK,
  2119. AA_VC_CALL_STATE_INCOMING_IN_PROGRESS))
  2120. {
  2121. AADEBUGP(AAD_WARNING,
  2122. ("Incoming close: VC 0x%x state is INCOMING_IN_PROGRESS; changing to ACTIVE\n",
  2123. pVc));
  2124. //
  2125. // We're getting a close call for an incoming call that is not yet
  2126. // in the connected state. Since we won't get any further notifications
  2127. // for this call, this call is effectively in the active state.
  2128. // So we set the state to active, and then close the VC.
  2129. // Note: we will not go down the InvalidateAtmEntryPath even
  2130. // if CloseStatus == NDIS_STATUS_DEST_OUT_OF_ORDER;
  2131. // we instead simply close the vc. (If the client is truly out of order,
  2132. // and we want to send to it, well separately try to make an OUTGOING
  2133. // call to the destination, which should fail with "DEST_OUT_OF_ORDER",
  2134. // and we'll end up eventually invalidating the atm entry.
  2135. //
  2136. AA_SET_FLAG(pVc->Flags,
  2137. AA_VC_CALL_STATE_MASK,
  2138. AA_VC_CALL_STATE_ACTIVE);
  2139. AtmArpReferenceVc(pVc); // Incoming call reference
  2140. VcAbnormalTermination = FALSE;
  2141. }
  2142. if (VcAbnormalTermination &&
  2143. (pVc->pAtmEntry != NULL_PATMARP_ATM_ENTRY))
  2144. {
  2145. pAtmEntry = pVc->pAtmEntry;
  2146. AADEBUGP(AAD_INFO,
  2147. ("IncomingClose: will invalidate ATM entry %x/%x - IP Entry %x, VC %x/%x\n",
  2148. pAtmEntry, pAtmEntry->Flags,
  2149. pAtmEntry->pIpEntryList,
  2150. pVc, pVc->Flags));
  2151. AA_RELEASE_VC_LOCK(pVc);
  2152. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2153. AtmArpInvalidateAtmEntry(
  2154. pAtmEntry,
  2155. FALSE // Not shutting down
  2156. );
  2157. //
  2158. // AE Lock is released within the above.
  2159. //
  2160. if (IsPVC)
  2161. {
  2162. //
  2163. // Start a CloseCall right here because InvalidateAtmEntry doesn't.
  2164. //
  2165. AA_ACQUIRE_VC_LOCK(pVc);
  2166. AtmArpCloseCall(pVc);
  2167. //
  2168. // VC lock is released above
  2169. }
  2170. }
  2171. else
  2172. {
  2173. AtmArpCloseCall(pVc);
  2174. }
  2175. AADEBUGP(AAD_LOUD, ("Leaving Incoming Close handler, VC: 0x%x\n", pVc));
  2176. return;
  2177. }
  2178. #ifdef IPMCAST
  2179. VOID
  2180. AtmArpAddParty(
  2181. IN PATMARP_ATM_ENTRY pAtmEntry,
  2182. IN PATMARP_IPMC_ATM_ENTRY pMcAtmEntry
  2183. )
  2184. /*++
  2185. Routine Description:
  2186. Add a party to an existing PMP connection. The ATM Entry contains
  2187. all address information for the connection, and the Multicast ATM
  2188. Entry represents one of the leaves, the one to be added.
  2189. NOTE: The caller is assumed to hold a lock for the ATM Entry,
  2190. which is released here.
  2191. Arguments:
  2192. pAtmEntry - Pointer to ATM Entry on which to add the leaf (party).
  2193. pMcAtmEntry - Points to ATM Multicast Entry representing the leaf.
  2194. Return Value:
  2195. None
  2196. --*/
  2197. {
  2198. PATMARP_VC pVc; // The VC structure for the connection
  2199. NDIS_HANDLE NdisVcHandle;
  2200. PCO_CALL_PARAMETERS pCallParameters;
  2201. ULONG RequestSize;
  2202. NDIS_STATUS Status;
  2203. AA_ASSERT(pAtmEntry->pVcList != NULL_PATMARP_VC);
  2204. pVc = pAtmEntry->pVcList;
  2205. NdisVcHandle = pVc->NdisVcHandle;
  2206. //
  2207. // Allocate all the space we need.
  2208. //
  2209. RequestSize = sizeof(CO_CALL_PARAMETERS) +
  2210. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  2211. sizeof(Q2931_CALLMGR_PARAMETERS) +
  2212. ATMARP_ADD_PARTY_IE_SPACE +
  2213. 0;
  2214. AA_ALLOC_MEM(pCallParameters, CO_CALL_PARAMETERS, RequestSize);
  2215. if (pCallParameters != (PCO_CALL_PARAMETERS)NULL)
  2216. {
  2217. //
  2218. // Fill in Call Parameters.
  2219. //
  2220. AtmArpFillCallParameters(
  2221. pCallParameters,
  2222. RequestSize,
  2223. &(pMcAtmEntry->ATMAddress), // Called address
  2224. &(pAtmEntry->pInterface->LocalAtmAddress), // Calling address
  2225. &(pVc->FlowSpec),
  2226. TRUE, // IsPMP
  2227. FALSE // IsMakeCall?
  2228. );
  2229. }
  2230. AA_SET_FLAG(pMcAtmEntry->Flags,
  2231. AA_IPMC_AE_CONN_STATE_MASK,
  2232. AA_IPMC_AE_CONN_WACK_ADD_PARTY);
  2233. pAtmEntry->pMcAtmInfo->TransientLeaves++;
  2234. AA_RELEASE_AE_LOCK(pAtmEntry);
  2235. if (pCallParameters != (PCO_CALL_PARAMETERS)NULL)
  2236. {
  2237. Status = NdisClAddParty(
  2238. NdisVcHandle,
  2239. (NDIS_HANDLE)pMcAtmEntry,
  2240. pCallParameters,
  2241. &(pMcAtmEntry->NdisPartyHandle)
  2242. );
  2243. }
  2244. else
  2245. {
  2246. Status = NDIS_STATUS_RESOURCES;
  2247. }
  2248. if (Status != NDIS_STATUS_PENDING)
  2249. {
  2250. AtmArpAddPartyCompleteHandler(
  2251. Status,
  2252. (NDIS_HANDLE)pMcAtmEntry,
  2253. pMcAtmEntry->NdisPartyHandle,
  2254. pCallParameters
  2255. );
  2256. }
  2257. }
  2258. VOID
  2259. AtmArpMcTerminateMember(
  2260. IN PATMARP_ATM_ENTRY pAtmEntry,
  2261. IN PATMARP_IPMC_ATM_ENTRY pMcAtmEntry
  2262. )
  2263. /*++
  2264. Routine Description:
  2265. Terminate the specified member of a multicast group. If it is
  2266. currently a leaf in the point-to-multipoint connection to the
  2267. group, then we drop it. If it is the LAST leaf, then we close
  2268. the entire connection.
  2269. NOTE: the caller is assumed to hold the ATM Entry lock, which
  2270. will be released here.
  2271. Arguments:
  2272. pAtmEntry - Pointer to ATM Entry
  2273. pMcAtmEntry - Points to ATM Multicast Entry representing the leaf to
  2274. be terminated.
  2275. Return Value:
  2276. None
  2277. --*/
  2278. {
  2279. PATMARP_IPMC_ATM_INFO pMcAtmInfo;
  2280. PATMARP_VC pVc;
  2281. NDIS_HANDLE NdisPartyHandle;
  2282. NDIS_STATUS Status;
  2283. pMcAtmInfo = pAtmEntry->pMcAtmInfo;
  2284. pVc = pAtmEntry->pVcList;
  2285. NdisPartyHandle = pMcAtmEntry->NdisPartyHandle;
  2286. AAMCDEBUGP(AAD_VERY_LOUD,
  2287. ("TerminateMember: pAtmEntry 0x%x, pMcAtmEntry 0x%x, pVc 0x%x, NdisPtyHnd 0x%x\n",
  2288. pAtmEntry, pMcAtmEntry, pVc, NdisPartyHandle));
  2289. #if DBG
  2290. {
  2291. PATMARP_IP_ENTRY pIpEntry = pAtmEntry->pIpEntryList;
  2292. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2293. {
  2294. AAMCDEBUGPMAP(AAD_INFO, "Terminating ",
  2295. &pIpEntry->IPAddress,
  2296. &pMcAtmEntry->ATMAddress);
  2297. }
  2298. }
  2299. #endif // DBG
  2300. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  2301. AA_IPMC_AE_GEN_STATE_MASK,
  2302. AA_IPMC_AE_TERMINATING))
  2303. {
  2304. AA_RELEASE_AE_LOCK(pAtmEntry);
  2305. return;
  2306. }
  2307. AA_SET_FLAG(pMcAtmEntry->Flags,
  2308. AA_IPMC_AE_GEN_STATE_MASK,
  2309. AA_IPMC_AE_TERMINATING);
  2310. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  2311. AA_IPMC_AE_CONN_STATE_MASK,
  2312. AA_IPMC_AE_CONN_ACTIVE))
  2313. {
  2314. if (pMcAtmInfo->ActiveLeaves == 1)
  2315. {
  2316. //
  2317. // This is the last active leaf in this connection. Close the call.
  2318. //
  2319. AA_RELEASE_AE_LOCK(pAtmEntry);
  2320. AA_ASSERT(pVc != NULL_PATMARP_VC);
  2321. AA_ACQUIRE_VC_LOCK(pVc);
  2322. AtmArpCloseCall(pVc);
  2323. //
  2324. // VC lock is released within the above.
  2325. //
  2326. }
  2327. else
  2328. {
  2329. //
  2330. // This isn't the only leaf in this connection. Drop this party.
  2331. //
  2332. pAtmEntry->pMcAtmInfo->ActiveLeaves--;
  2333. AA_SET_FLAG(pMcAtmEntry->Flags,
  2334. AA_IPMC_AE_CONN_STATE_MASK,
  2335. AA_IPMC_AE_CONN_WACK_DROP_PARTY);
  2336. AA_RELEASE_AE_LOCK(pAtmEntry);
  2337. Status = NdisClDropParty(
  2338. NdisPartyHandle,
  2339. NULL, // Buffer
  2340. (UINT)0 // Size
  2341. );
  2342. if (Status != NDIS_STATUS_PENDING)
  2343. {
  2344. AtmArpDropPartyCompleteHandler(
  2345. Status,
  2346. (NDIS_HANDLE)pMcAtmEntry
  2347. );
  2348. }
  2349. }
  2350. }
  2351. else if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  2352. AA_IPMC_AE_CONN_STATE_MASK,
  2353. AA_IPMC_AE_CONN_DISCONNECTED))
  2354. {
  2355. //
  2356. // Simply unlink this entry.
  2357. //
  2358. UINT rc;
  2359. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // temp ref
  2360. AtmArpMcUnlinkAtmMember(pAtmEntry, pMcAtmEntry);
  2361. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // temp ref
  2362. if (rc!=0)
  2363. {
  2364. AA_RELEASE_AE_LOCK(pAtmEntry);
  2365. }
  2366. }
  2367. else
  2368. {
  2369. //
  2370. // This party is in a transient state. Let it finish its current
  2371. // operation.
  2372. //
  2373. AA_RELEASE_AE_LOCK(pAtmEntry);
  2374. }
  2375. }
  2376. #endif // IPMCAST
  2377. VOID
  2378. AtmArpIncomingDropPartyHandler(
  2379. IN NDIS_STATUS DropStatus,
  2380. IN NDIS_HANDLE ProtocolPartyContext,
  2381. IN PVOID pCloseData OPTIONAL,
  2382. IN UINT Size OPTIONAL
  2383. )
  2384. /*++
  2385. Routine Description:
  2386. This handler is called if the network (or remote peer) drops
  2387. a leaf node from a point-to-multipoint call rooted at us.
  2388. See Section 5.1.5.1 in RFC 2022: we delete the member from
  2389. the multicast group it belongs to. And we start a timer at
  2390. the end of which we mark the multicast group as needing
  2391. revalidation.
  2392. Arguments:
  2393. DropStatus - Leaf drop status
  2394. ProtocolPartyContext - Pointer to our Multicast ATM Entry structure
  2395. pCloseData - Optional additional info (ignored)
  2396. Size - of the above (ignored)
  2397. Return Value:
  2398. None
  2399. --*/
  2400. {
  2401. #ifdef IPMCAST
  2402. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  2403. PATMARP_ATM_ENTRY pAtmEntry;
  2404. PATMARP_IP_ENTRY pIpEntry;
  2405. PATMARP_INTERFACE pInterface;
  2406. NDIS_HANDLE NdisPartyHandle;
  2407. NDIS_STATUS Status;
  2408. ULONG rc;
  2409. pMcAtmEntry = (PATMARP_IPMC_ATM_ENTRY)ProtocolPartyContext;
  2410. AA_STRUCT_ASSERT(pMcAtmEntry, ame);
  2411. AA_ASSERT(pMcAtmEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  2412. AA_ASSERT(pMcAtmEntry->pAtmEntry->pIpEntryList != NULL_PATMARP_IP_ENTRY);
  2413. pAtmEntry = pMcAtmEntry->pAtmEntry;
  2414. NdisPartyHandle = pMcAtmEntry->NdisPartyHandle;
  2415. pInterface = pAtmEntry->pInterface;
  2416. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  2417. pIpEntry = pAtmEntry->pIpEntryList;
  2418. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2419. {
  2420. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  2421. AA_REF_IE(pIpEntry, IE_REFTYPE_TMP); // TmpRef
  2422. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  2423. }
  2424. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  2425. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2426. AADEBUGP(AAD_INFO,
  2427. ("Incoming Drop: pMcAtmEntry 0x%x, PtyHnd 0x%x, pAtmEntry 0x%x, IP Addr: %d.%d.%d.%d\n",
  2428. pMcAtmEntry,
  2429. NdisPartyHandle,
  2430. pAtmEntry,
  2431. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  2432. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  2433. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  2434. ((PUCHAR)&(pIpEntry->IPAddress))[3]));
  2435. pAtmEntry->pMcAtmInfo->ActiveLeaves--;
  2436. AA_SET_FLAG(pMcAtmEntry->Flags,
  2437. AA_IPMC_AE_CONN_STATE_MASK,
  2438. AA_IPMC_AE_CONN_RCV_DROP_PARTY);
  2439. AA_RELEASE_AE_LOCK(pAtmEntry);
  2440. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2441. {
  2442. //
  2443. // We need to revalidate this multicast group after a random
  2444. // delay. Start a random delay timer.
  2445. //
  2446. AA_ACQUIRE_IE_LOCK(pIpEntry);
  2447. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  2448. if (!AA_IS_TIMER_ACTIVE(&(pIpEntry->Timer)) &&
  2449. AA_IS_FLAG_SET(pIpEntry->Flags,
  2450. AA_IP_ENTRY_MC_RESOLVE_MASK,
  2451. AA_IP_ENTRY_MC_RESOLVED))
  2452. {
  2453. ULONG RandomDelay;
  2454. RandomDelay = AA_GET_RANDOM(
  2455. pInterface->MinRevalidationDelay,
  2456. pInterface->MaxRevalidationDelay);
  2457. AtmArpStartTimer(
  2458. pInterface,
  2459. &(pIpEntry->Timer),
  2460. AtmArpMcRevalidationDelayTimeout,
  2461. RandomDelay,
  2462. (PVOID)pIpEntry
  2463. );
  2464. AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
  2465. }
  2466. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TMP);
  2467. if (rc != 0)
  2468. {
  2469. AA_RELEASE_IE_LOCK(pIpEntry);
  2470. }
  2471. }
  2472. //
  2473. // Complete the DropParty handshake.
  2474. //
  2475. Status = NdisClDropParty(
  2476. NdisPartyHandle,
  2477. NULL,
  2478. 0
  2479. );
  2480. if (Status != NDIS_STATUS_PENDING)
  2481. {
  2482. AtmArpDropPartyCompleteHandler(
  2483. Status,
  2484. (NDIS_HANDLE)pMcAtmEntry
  2485. );
  2486. }
  2487. #endif // IPMCAST
  2488. return;
  2489. }
  2490. VOID
  2491. AtmArpQosChangeHandler(
  2492. IN NDIS_HANDLE ProtocolVcContext,
  2493. IN PCO_CALL_PARAMETERS pCallParameters
  2494. )
  2495. /*++
  2496. Routine Description:
  2497. This handler is called if the remote peer modifies call parameters
  2498. "on the fly", i.e. after the call is established and running.
  2499. This isn't supported by existing ATM signalling, and shouldn't happen,
  2500. but we'll allow this.
  2501. FUTURE: The FlowSpecs associated with the call are affected by this.
  2502. Arguments:
  2503. ProtocolVcContext - Pointer to our ATMARP VC structure
  2504. pCallParameters - updated call parameters.
  2505. Return Value:
  2506. None
  2507. --*/
  2508. {
  2509. PATMARP_VC pVc;
  2510. pVc = (PATMARP_VC)ProtocolVcContext;
  2511. AADEBUGP(AAD_WARNING, ("Ignoring Qos Change, VC: 0x%x\n", pVc));
  2512. return;
  2513. }
  2514. VOID
  2515. AtmArpOpenAfCompleteHandler(
  2516. IN NDIS_STATUS Status,
  2517. IN NDIS_HANDLE ProtocolAfContext,
  2518. IN NDIS_HANDLE NdisAfHandle
  2519. )
  2520. /*++
  2521. Routine Description:
  2522. This handler is called to indicate completion of a previous call
  2523. to NdisClOpenAddressFamily. We would have blocked the thread that
  2524. called this. Wake it up now.
  2525. By the way, if the call was successful, store the NDIS AF handle
  2526. in our Interface structure.
  2527. We don't need to acquire locks here because the thread that called
  2528. OpenAddressFamily would have blocked with a lock acquired.
  2529. Arguments:
  2530. Status - Status of the Open AF
  2531. ProtocolAfContext - Pointer to our ATMARP Interface structure
  2532. NdisAfHandle - NDIS handle to the AF association
  2533. Return Value:
  2534. None
  2535. --*/
  2536. {
  2537. PATMARP_INTERFACE pInterface;
  2538. pInterface = (PATMARP_INTERFACE)ProtocolAfContext;
  2539. AA_STRUCT_ASSERT(pInterface, aai);
  2540. AADEBUGP(AAD_INFO, ("Open AF Complete: IF 0x%x, Status 0x%x, AF Handle 0x%x\n",
  2541. pInterface, Status, NdisAfHandle));
  2542. if (Status == NDIS_STATUS_SUCCESS)
  2543. {
  2544. pInterface->NdisAfHandle = NdisAfHandle;
  2545. }
  2546. //
  2547. // Wake up the blocked thread
  2548. //
  2549. AA_SIGNAL_BLOCK_STRUCT(&(pInterface->Block), Status);
  2550. }
  2551. VOID
  2552. AtmArpSendIPDelInterface(
  2553. IN PNDIS_WORK_ITEM pWorkItem,
  2554. IN PVOID IfContext
  2555. )
  2556. {
  2557. PATMARP_INTERFACE pInterface;
  2558. PVOID IPContext;
  2559. ULONG rc;
  2560. #if DBG
  2561. AA_IRQL EntryIrq, ExitIrq;
  2562. #endif
  2563. AA_GET_ENTRY_IRQL(EntryIrq);
  2564. #if !BINARY_COMPATIBLE
  2565. AA_ASSERT(EntryIrq == PASSIVE_LEVEL);
  2566. #endif
  2567. pInterface = (PATMARP_INTERFACE)IfContext;
  2568. AA_STRUCT_ASSERT(pInterface, aai);
  2569. AA_FREE_MEM(pWorkItem);
  2570. AA_ACQUIRE_IF_LOCK(pInterface);
  2571. IPContext = pInterface->IPContext;
  2572. pInterface->IPContext = NULL;
  2573. AA_RELEASE_IF_LOCK(pInterface);
  2574. AADEBUGP(AAD_INFO, ("SendIPDelInterface: IF 0x%x, IPContext 0x%x\n",
  2575. pInterface, IPContext));
  2576. if (IPContext != NULL)
  2577. {
  2578. (*(pAtmArpGlobalInfo->pIPDelInterfaceRtn))(
  2579. IPContext
  2580. #if IFCHANGE1
  2581. #ifndef ATMARP_WIN98
  2582. ,0 // DeleteIndex (unused) -- See 10/14/1998 entry
  2583. // in notes.txt
  2584. #endif
  2585. #endif // IFCHANGE1
  2586. );
  2587. }
  2588. else
  2589. {
  2590. AADEBUGP(AAD_INFO, ("SendIPDelInterface: NO IPContext"));
  2591. }
  2592. AA_ACQUIRE_IF_LOCK(pInterface);
  2593. rc = AtmArpDereferenceInterface(pInterface); // Work Item: Del Interface
  2594. if (rc != 0)
  2595. {
  2596. AA_RELEASE_IF_LOCK(pInterface);
  2597. }
  2598. //
  2599. // else the Interface is gone.
  2600. //
  2601. }
  2602. VOID
  2603. AtmArpCloseAfCompleteHandler(
  2604. IN NDIS_STATUS Status,
  2605. IN NDIS_HANDLE ProtocolAfContext
  2606. )
  2607. /*++
  2608. Routine Description:
  2609. This routine is called to indicate completion of a call to
  2610. NdisClCloseAddressFamily. Tell IP to Delete this Interface now.
  2611. Arguments:
  2612. Status - Status of the Close AF (ignored here)
  2613. ProtocolAfContext - Pointer to ATMARP Interface structure
  2614. Return Value:
  2615. None
  2616. --*/
  2617. {
  2618. PATMARP_INTERFACE pInterface;
  2619. PNDIS_WORK_ITEM pWorkItem;
  2620. NDIS_STATUS NdisStatus;
  2621. BOOLEAN bUnloading;
  2622. #if 0
  2623. PVOID IPContext;
  2624. #endif
  2625. #if DBG
  2626. AA_IRQL EntryIrq, ExitIrq;
  2627. #endif
  2628. AA_GET_ENTRY_IRQL(EntryIrq);
  2629. #if !BINARY_COMPATIBLE
  2630. AA_ASSERT(EntryIrq == PASSIVE_LEVEL);
  2631. #endif
  2632. AA_ASSERT(Status == NDIS_STATUS_SUCCESS);
  2633. pInterface = (PATMARP_INTERFACE)ProtocolAfContext;
  2634. AADEBUGP(AAD_INFO, ("CloseAfComplete: If 0x%x, Status 0x%x\n",
  2635. pInterface, Status));
  2636. AA_STRUCT_ASSERT(pInterface, aai);
  2637. AA_ACQUIRE_IF_LOCK(pInterface);
  2638. pInterface->NdisAfHandle = NULL;
  2639. bUnloading = pAtmArpGlobalInfo->bUnloading;
  2640. if (pInterface->IPContext != NULL)
  2641. {
  2642. //
  2643. // We haven't seen an IfClose yet.
  2644. //
  2645. AA_ALLOC_MEM(pWorkItem, NDIS_WORK_ITEM, sizeof(NDIS_WORK_ITEM));
  2646. if (pWorkItem == NULL)
  2647. {
  2648. AA_ASSERT(FALSE);
  2649. AA_RELEASE_IF_LOCK(pInterface);
  2650. return;
  2651. }
  2652. #if 0
  2653. IPContext = (PVOID)pInterface->IPContext;
  2654. pInterface->IPContext = NULL;
  2655. #endif
  2656. AtmArpReferenceInterface(pInterface); // Work Item
  2657. AA_RELEASE_IF_LOCK(pInterface);
  2658. if (bUnloading)
  2659. {
  2660. AtmArpSendIPDelInterface(pWorkItem, (PVOID)pInterface);
  2661. }
  2662. else
  2663. {
  2664. //
  2665. // Queue a work item so that (a) things unravel easier,
  2666. // (b) we are at passive level when we call IPDelInterface.
  2667. //
  2668. NdisInitializeWorkItem(
  2669. pWorkItem,
  2670. AtmArpSendIPDelInterface,
  2671. (PVOID)pInterface
  2672. );
  2673. NdisStatus = NdisScheduleWorkItem(pWorkItem);
  2674. AA_ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
  2675. }
  2676. }
  2677. else
  2678. {
  2679. AADEBUGP(AAD_WARNING, ("CloseAfComplete: NO IPContext"));
  2680. AA_RELEASE_IF_LOCK(pInterface);
  2681. }
  2682. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  2683. }
  2684. VOID
  2685. AtmArpRegisterSapCompleteHandler(
  2686. IN NDIS_STATUS Status,
  2687. IN NDIS_HANDLE ProtocolSapContext,
  2688. IN PCO_SAP pSap,
  2689. IN NDIS_HANDLE NdisSapHandle
  2690. )
  2691. /*++
  2692. Routine Description:
  2693. This routine is called to indicate completion of a call to
  2694. NdisClRegisterSap. If the call was successful, save the
  2695. allocated NdisSapHandle in our SAP structure.
  2696. Arguments:
  2697. Status - Status of Register SAP
  2698. ProtocolSapContext - Pointer to our ATMARP Interface structure
  2699. pSap - SAP information we'd passed in the call
  2700. NdisSapHandle - SAP Handle
  2701. Return Value:
  2702. None
  2703. --*/
  2704. {
  2705. PATMARP_SAP pAtmArpSap;
  2706. pAtmArpSap = (PATMARP_SAP)ProtocolSapContext;
  2707. if (Status == NDIS_STATUS_SUCCESS)
  2708. {
  2709. pAtmArpSap->NdisSapHandle = NdisSapHandle;
  2710. AA_SET_FLAG(pAtmArpSap->Flags,
  2711. AA_SAP_REG_STATE_MASK,
  2712. AA_SAP_REG_STATE_REGISTERED);
  2713. }
  2714. else
  2715. {
  2716. AA_SET_FLAG(pAtmArpSap->Flags,
  2717. AA_SAP_REG_STATE_MASK,
  2718. AA_SAP_REG_STATE_IDLE);
  2719. }
  2720. }
  2721. VOID
  2722. AtmArpDeregisterSapCompleteHandler(
  2723. IN NDIS_STATUS Status,
  2724. IN NDIS_HANDLE ProtocolSapContext
  2725. )
  2726. /*++
  2727. Routine Description:
  2728. This routine is called when a previous call to NdisClDeregisterSap
  2729. has completed. If it was successful, we update the state of the ATMARP
  2730. SAP structure representing the Sap.
  2731. Arguments:
  2732. Status - Status of the Deregister SAP request
  2733. ProtocolSapContext - Pointer to our ATMARP SAP structure
  2734. Return Value:
  2735. None
  2736. --*/
  2737. {
  2738. PATMARP_INTERFACE pInterface;
  2739. PATMARP_SAP pAtmArpSap;
  2740. if (Status == NDIS_STATUS_SUCCESS)
  2741. {
  2742. pAtmArpSap = (PATMARP_SAP)ProtocolSapContext;
  2743. AA_STRUCT_ASSERT(pAtmArpSap, aas);
  2744. pInterface = pAtmArpSap->pInterface;
  2745. AA_ACQUIRE_IF_LOCK(pInterface);
  2746. pAtmArpSap->NdisSapHandle = NULL;
  2747. AA_SET_FLAG(pAtmArpSap->Flags,
  2748. AA_SAP_REG_STATE_MASK,
  2749. AA_SAP_REG_STATE_IDLE);
  2750. AA_RELEASE_IF_LOCK(pInterface);
  2751. }
  2752. return;
  2753. }
  2754. VOID
  2755. AtmArpMakeCallCompleteHandler(
  2756. IN NDIS_STATUS Status,
  2757. IN NDIS_HANDLE ProtocolVcContext,
  2758. IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
  2759. IN PCO_CALL_PARAMETERS pCallParameters
  2760. )
  2761. /*++
  2762. Routine Description:
  2763. This routine is called when an outgoing call request (NdisClMakeCall)
  2764. has completed. The "Status" parameter indicates whether the call was
  2765. successful or not.
  2766. If the call was successful, we send any packets queued for transmission
  2767. on this VC.
  2768. If the call failed, we free any packets queued on this VC and unlink it
  2769. from the ATM Address Entry it was linked to. If this was an attempt to
  2770. connect to the ATMARP server, delay for a while before attempting to
  2771. connect again.
  2772. Arguments:
  2773. Status - Result of the NdisClMakeCall
  2774. ProtocolVcContext - Pointer to ATMARP VC structure
  2775. NdisPartyHandle - Not used (no point-to-multipoint calls)
  2776. pCallParameters - Pointer to call parameters
  2777. Return Value:
  2778. None
  2779. --*/
  2780. {
  2781. PATMARP_VC pVc;
  2782. PATMARP_INTERFACE pInterface;
  2783. ULONG rc; // ref count
  2784. BOOLEAN IsServerVc; // Is this the VC to the ATMARP server?
  2785. BOOLEAN IsPMP;
  2786. PNDIS_PACKET PacketList; // List of packets waiting to be sent
  2787. AA_HEADER_TYPE HdrType; // header types for the above
  2788. BOOLEAN HdrPresent;
  2789. NDIS_HANDLE NdisVcHandle;
  2790. PATMARP_ATM_ENTRY pAtmEntry; // ATM Entry to which this VC is linked
  2791. Q2931_CALLMGR_PARAMETERS UNALIGNED * pCallMgrSpecific;
  2792. Q2931_IE UNALIGNED * pIe;
  2793. ULONG InfoElementCount;
  2794. //
  2795. // Initialize
  2796. //
  2797. PacketList = (PNDIS_PACKET)NULL;
  2798. pVc = (PATMARP_VC)ProtocolVcContext;
  2799. AA_STRUCT_ASSERT(pVc, avc);
  2800. AADEBUGP(AAD_INFO, ("MakeCall Complete: Status 0x%x, VC 0x%x, pAtmEntry 0x%x\n",
  2801. Status, pVc, pVc->pAtmEntry));
  2802. AA_ACQUIRE_VC_LOCK(pVc);
  2803. IsPMP = AA_IS_FLAG_SET(pVc->Flags,
  2804. AA_VC_CONN_TYPE_MASK,
  2805. AA_VC_CONN_TYPE_PMP);
  2806. pAtmEntry = pVc->pAtmEntry;
  2807. AA_ASSERT(pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  2808. if (pVc->FlowSpec.Encapsulation == ENCAPSULATION_TYPE_LLCSNAP)
  2809. {
  2810. HdrType = (IsPMP? AA_HEADER_TYPE_NUNICAST: AA_HEADER_TYPE_UNICAST);
  2811. HdrPresent = TRUE;
  2812. }
  2813. else
  2814. {
  2815. HdrType = AA_HEADER_TYPE_NONE;
  2816. HdrPresent = FALSE;
  2817. }
  2818. pInterface = pVc->pInterface;
  2819. if (pInterface->AdminState == IF_STATUS_UP)
  2820. {
  2821. if (Status == NDIS_STATUS_SUCCESS)
  2822. {
  2823. AADEBUGP(AAD_LOUD, ("Make Call Successful on VC 0x%x\n", pVc));
  2824. //
  2825. // Update the call state on this VC, and send queued packets.
  2826. // If this happens to be the VC to the ATMARP Server, we expect
  2827. // to see our initial ARP Request (to register with the server)
  2828. // in this queue.
  2829. //
  2830. AA_SET_FLAG(pVc->Flags,
  2831. AA_VC_CALL_STATE_MASK,
  2832. AA_VC_CALL_STATE_ACTIVE);
  2833. //
  2834. // Locate the AAL parameters Info Element, and get the updated
  2835. // packet sizes.
  2836. //
  2837. pCallMgrSpecific = (PQ2931_CALLMGR_PARAMETERS)&pCallParameters->CallMgrParameters->CallMgrSpecific.Parameters[0];
  2838. pIe = (PQ2931_IE)&pCallMgrSpecific->InfoElements[0];
  2839. for (InfoElementCount = 0;
  2840. InfoElementCount < pCallMgrSpecific->InfoElementCount;
  2841. InfoElementCount++)
  2842. {
  2843. if (pIe->IEType == IE_AALParameters)
  2844. {
  2845. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  2846. UNALIGNED AAL5_PARAMETERS * pAal5;
  2847. pAalIe = (PAAL_PARAMETERS_IE)&pIe->IE[0];
  2848. AA_ASSERT(pAalIe->AALType == AAL_TYPE_AAL5);
  2849. pAal5 = &pAalIe->AALSpecificParameters.AAL5Parameters;
  2850. #if DBG
  2851. if (pVc->FlowSpec.SendMaxSize != pAal5->ForwardMaxCPCSSDUSize)
  2852. {
  2853. AADEBUGP(AAD_INFO,
  2854. ("CallComplete: Send size changed (%d->%d)\n",
  2855. pVc->FlowSpec.SendMaxSize,
  2856. pAal5->ForwardMaxCPCSSDUSize));
  2857. }
  2858. if (pVc->FlowSpec.ReceiveMaxSize != pAal5->BackwardMaxCPCSSDUSize)
  2859. {
  2860. AADEBUGP(AAD_INFO,
  2861. ("CallComplete: Receive size changed (%d->%d)\n",
  2862. pVc->FlowSpec.ReceiveMaxSize,
  2863. pAal5->BackwardMaxCPCSSDUSize));
  2864. }
  2865. #endif // DBG
  2866. pVc->FlowSpec.SendMaxSize = pAal5->ForwardMaxCPCSSDUSize;
  2867. pVc->FlowSpec.ReceiveMaxSize = pAal5->BackwardMaxCPCSSDUSize;
  2868. break;
  2869. }
  2870. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  2871. }
  2872. AA_ASSERT(InfoElementCount != pCallMgrSpecific->InfoElementCount);
  2873. //
  2874. // Update the call type on this VC. If this is an SVC, start
  2875. // the VC aging timer.
  2876. //
  2877. if (pCallParameters->Flags & PERMANENT_VC)
  2878. {
  2879. AA_SET_FLAG(pVc->Flags,
  2880. AA_VC_TYPE_MASK,
  2881. AA_VC_TYPE_PVC);
  2882. }
  2883. else
  2884. {
  2885. ULONG AgingTime;
  2886. AA_SET_FLAG(pVc->Flags,
  2887. AA_VC_TYPE_MASK,
  2888. AA_VC_TYPE_SVC);
  2889. #ifdef IPMCAST
  2890. if (IsPMP)
  2891. {
  2892. AgingTime = pInterface->MulticastEntryAgingTimeout;
  2893. }
  2894. else
  2895. {
  2896. AgingTime = pVc->FlowSpec.AgingTime;
  2897. }
  2898. #else
  2899. AgingTime = pVc->FlowSpec.AgingTime;
  2900. #endif // IPMCAST
  2901. //
  2902. // Start VC aging timer on this SVC.
  2903. //
  2904. if (AgingTime != 0)
  2905. {
  2906. AtmArpStartTimer(
  2907. pInterface,
  2908. &(pVc->Timer),
  2909. AtmArpVcAgingTimeout,
  2910. AgingTime,
  2911. (PVOID)pVc
  2912. );
  2913. AtmArpReferenceVc(pVc); // Timer ref
  2914. }
  2915. }
  2916. AtmArpStartSendsOnVc(pVc);
  2917. //
  2918. // The VC lock is released within StartSendsOnVc()
  2919. //
  2920. #ifdef IPMCAST
  2921. if (IsPMP)
  2922. {
  2923. AtmArpMcMakeCallComplete(
  2924. pAtmEntry,
  2925. NdisPartyHandle,
  2926. Status
  2927. );
  2928. }
  2929. #endif // IPMCAST
  2930. }
  2931. else
  2932. {
  2933. //
  2934. // The call failed.
  2935. //
  2936. AA_SET_FLAG(pVc->Flags,
  2937. AA_VC_CALL_STATE_MASK,
  2938. AA_VC_CALL_STATE_IDLE);
  2939. //
  2940. // Delete the Call reference
  2941. //
  2942. rc = AtmArpDereferenceVc(pVc);
  2943. AA_ASSERT(rc > 0);
  2944. //
  2945. // Remove all packets queued on this VC
  2946. //
  2947. PacketList = pVc->PacketList;
  2948. pVc->PacketList = (PNDIS_PACKET)NULL;
  2949. //
  2950. // Was this a call to the ATMARP server?
  2951. //
  2952. if (pInterface->pCurrentServer != NULL)
  2953. {
  2954. IsServerVc = (pVc->pAtmEntry == pInterface->pCurrentServer->pAtmEntry);
  2955. }
  2956. else
  2957. {
  2958. IsServerVc = FALSE;
  2959. }
  2960. AADEBUGP(AAD_INFO,
  2961. ("Make Call FAILED on VC 0x%x IsPMP=%lu IsServer=%lu\n",
  2962. pVc,
  2963. IsPMP,
  2964. IsServerVc
  2965. ));
  2966. #ifdef GPC
  2967. //
  2968. // Unlink this VC from the flow, if linked...
  2969. //
  2970. if (pVc->FlowHandle != NULL)
  2971. {
  2972. PATMARP_FLOW_INFO pFlowInfo = (PATMARP_FLOW_INFO)pVc->FlowHandle;
  2973. if ((PVOID)pVc == InterlockedCompareExchangePointer(
  2974. &(pFlowInfo->VcContext),
  2975. NULL,
  2976. pVc
  2977. ))
  2978. {
  2979. pVc->FlowHandle = NULL;
  2980. rc = AtmArpDereferenceVc(pVc); // Unlink from GPC Flow
  2981. AA_ASSERT(rc > 0);
  2982. }
  2983. }
  2984. #endif // GPC
  2985. //
  2986. // Unlink this VC from the ATM Entry it belonged to, if any
  2987. //
  2988. AA_ASSERT(pVc->pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  2989. AtmArpUnlinkVcFromAtmEntry(pVc, FALSE);
  2990. //
  2991. // Delete the ATM Entry reference
  2992. //
  2993. rc = AtmArpDereferenceVc(pVc); // ATM Entry ref
  2994. AA_ASSERT(rc > 0);
  2995. //
  2996. // Delete the CreateVc reference
  2997. //
  2998. NdisVcHandle = pVc->NdisVcHandle;
  2999. rc = AtmArpDereferenceVc(pVc); // Create Vc ref
  3000. if (rc != 0)
  3001. {
  3002. AA_RELEASE_VC_LOCK(pVc);
  3003. }
  3004. #ifndef VC_REFS_ON_SENDS
  3005. //
  3006. // Delete the NDIS association
  3007. //
  3008. (VOID)NdisCoDeleteVc(NdisVcHandle);
  3009. #endif // VC_REFS_ON_SENDS
  3010. AADEBUGP(AAD_LOUD, ("Deleted NDIS VC on pVc 0x%x: NdisVcHandle 0x%x\n",
  3011. pVc, NdisVcHandle));
  3012. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3013. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_VC); // Unlink Vc - make call
  3014. if (rc != 0)
  3015. {
  3016. AA_RELEASE_AE_LOCK(pAtmEntry);
  3017. #ifdef IPMCAST
  3018. if (IsPMP)
  3019. {
  3020. AtmArpMcMakeCallComplete(
  3021. pAtmEntry,
  3022. NdisPartyHandle,
  3023. Status
  3024. );
  3025. }
  3026. else
  3027. {
  3028. #endif // IPMCAST
  3029. if (!AA_IS_TRANSIENT_FAILURE(Status))
  3030. {
  3031. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3032. AtmArpInvalidateAtmEntry(pAtmEntry, FALSE); // MakeCall failure
  3033. //
  3034. // AE Lock is released within the above.
  3035. //
  3036. }
  3037. #ifdef IPMCAST
  3038. }
  3039. #endif // IPMCAST
  3040. }
  3041. //
  3042. // else the ATM Entry is gone
  3043. //
  3044. if (IsServerVc)
  3045. {
  3046. BOOLEAN WasRunning;
  3047. AA_ACQUIRE_IF_LOCK(pInterface);
  3048. //
  3049. // If we were in the process of registering (or refreshing)
  3050. // ourselves with the server, then retry after a while.
  3051. //
  3052. if (AA_IS_FLAG_SET(
  3053. pInterface->Flags,
  3054. AA_IF_SERVER_STATE_MASK,
  3055. AA_IF_SERVER_REGISTERING))
  3056. {
  3057. AA_SET_FLAG(pInterface->Flags,
  3058. AA_IF_SERVER_STATE_MASK,
  3059. AA_IF_SERVER_NO_CONTACT);
  3060. //
  3061. // The server registration timer would have been
  3062. // started -- stop it first.
  3063. //
  3064. WasRunning = AtmArpStopTimer(&(pInterface->Timer), pInterface);
  3065. if (WasRunning)
  3066. {
  3067. rc = AtmArpDereferenceInterface(pInterface);
  3068. }
  3069. else
  3070. {
  3071. rc = pInterface->RefCount;
  3072. }
  3073. if (rc > 0)
  3074. {
  3075. AtmArpRetryServerRegistration(pInterface);
  3076. //
  3077. // The IF lock is released within the above.
  3078. //
  3079. }
  3080. //
  3081. // else the IF is gone!
  3082. //
  3083. }
  3084. else
  3085. {
  3086. //
  3087. // We might have been trying to set up the server VC
  3088. // because of other reasons:
  3089. // - to resolve an unknown IP address
  3090. // - the server ATM address might be shared with other
  3091. // services (e.g. DHCP server)
  3092. //
  3093. // We don't have to retry registration in these cases.
  3094. //
  3095. AA_RELEASE_IF_LOCK(pInterface);
  3096. }
  3097. }
  3098. }
  3099. }
  3100. else
  3101. {
  3102. //
  3103. // The Interface is going down: clean up everything first.
  3104. //
  3105. if (Status == NDIS_STATUS_SUCCESS)
  3106. {
  3107. AA_SET_FLAG(pVc->Flags,
  3108. AA_VC_CALL_STATE_MASK,
  3109. AA_VC_CALL_STATE_ACTIVE);
  3110. //
  3111. // The call had been set up successfully, so close it.
  3112. // AtmArpCloseCall also frees any queued packets on the VC.
  3113. //
  3114. AtmArpCloseCall(pVc);
  3115. //
  3116. // The VC lock is released by CloseCall
  3117. //
  3118. }
  3119. else
  3120. {
  3121. // MakeCall had failed. (And the IF is going down)
  3122. AA_SET_FLAG(pVc->Flags,
  3123. AA_VC_CALL_STATE_MASK,
  3124. AA_VC_CALL_STATE_IDLE);
  3125. //
  3126. // Remove all packets queued on this VC
  3127. //
  3128. PacketList = pVc->PacketList;
  3129. pVc->PacketList = (PNDIS_PACKET)NULL;
  3130. NdisVcHandle = pVc->NdisVcHandle;
  3131. AtmArpUnlinkVcFromAtmEntry(pVc, TRUE);
  3132. //
  3133. // Delete the ATM Entry reference
  3134. //
  3135. rc = AtmArpDereferenceVc(pVc); // ATM Entry ref
  3136. //
  3137. // Delete the Call reference
  3138. //
  3139. rc = AtmArpDereferenceVc(pVc);
  3140. AA_ASSERT(rc > 0);
  3141. //
  3142. // Delete the CreateVc reference
  3143. //
  3144. rc = AtmArpDereferenceVc(pVc); // Create Vc ref
  3145. if (rc != 0)
  3146. {
  3147. AA_RELEASE_VC_LOCK(pVc);
  3148. }
  3149. #ifndef VC_REFS_ON_SENDS
  3150. //
  3151. // Delete the NDIS association
  3152. //
  3153. (VOID)NdisCoDeleteVc(NdisVcHandle);
  3154. AADEBUGP(AAD_LOUD,
  3155. ("MakeCall Fail: Deleted NDIS VC on pVc 0x%x: NdisVcHandle 0x%x\n",
  3156. pVc, NdisVcHandle));
  3157. #endif // !VC_REFS_ON_SENDS
  3158. }
  3159. }
  3160. //
  3161. // If there was a failure in making the call, or we aborted
  3162. // it for some reason, free all packets that were queued
  3163. // on the VC.
  3164. //
  3165. if (PacketList != (PNDIS_PACKET)NULL)
  3166. {
  3167. AtmArpFreeSendPackets(
  3168. pInterface,
  3169. PacketList,
  3170. HdrPresent
  3171. );
  3172. }
  3173. //
  3174. // We would have allocated the Call Parameters in MakeCall().
  3175. // We don't need it anymore.
  3176. //
  3177. AA_FREE_MEM(pCallParameters);
  3178. return;
  3179. }
  3180. #ifdef IPMCAST
  3181. VOID
  3182. AtmArpMcMakeCallComplete(
  3183. IN PATMARP_ATM_ENTRY pAtmEntry,
  3184. IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
  3185. IN NDIS_STATUS Status
  3186. )
  3187. /*++
  3188. Routine Description:
  3189. Post-processing of a PMP MakeCall completion.
  3190. Arguments:
  3191. pAtmEntry - Represents the multicast group to which
  3192. the call was made.
  3193. NdisPartyHandle - Returned from the MakeCall.
  3194. Status - Result of the MakeCall
  3195. Return Value:
  3196. None
  3197. --*/
  3198. {
  3199. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  3200. PATMARP_IPMC_ATM_ENTRY * ppMcAtmEntry;
  3201. PATMARP_IPMC_ATM_INFO pMcAtmInfo;
  3202. PATMARP_IP_ENTRY pIpEntry;
  3203. PATMARP_INTERFACE pInterface;
  3204. //
  3205. // Do we need to update the PMP connection as a result
  3206. // of this event?
  3207. //
  3208. BOOLEAN bWantConnUpdate;
  3209. ULONG DelayBeforeRetry;
  3210. BOOLEAN bAtmEntryLockAcquired;
  3211. bAtmEntryLockAcquired = TRUE;
  3212. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3213. AA_ASSERT(pAtmEntry->pMcAtmInfo != NULL_PATMARP_IPMC_ATM_INFO);
  3214. AA_ASSERT(pAtmEntry->pIpEntryList != NULL_PATMARP_IP_ENTRY);
  3215. pIpEntry = pAtmEntry->pIpEntryList;
  3216. pMcAtmInfo = pAtmEntry->pMcAtmInfo;
  3217. pInterface = pAtmEntry->pInterface;
  3218. bWantConnUpdate = FALSE;
  3219. pMcAtmInfo->TransientLeaves--;
  3220. //
  3221. // Locate the MC ATM Entry representing the first party.
  3222. //
  3223. for (pMcAtmEntry = pMcAtmInfo->pMcAtmEntryList;
  3224. /* NONE */;
  3225. pMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry)
  3226. {
  3227. AA_ASSERT(pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY);
  3228. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  3229. AA_IPMC_AE_CONN_STATE_MASK,
  3230. AA_IPMC_AE_CONN_WACK_ADD_PARTY))
  3231. {
  3232. break;
  3233. }
  3234. }
  3235. AAMCDEBUGP(AAD_INFO,
  3236. ("McMakeCallComplete: pAtmEntry 0x%x, pMcAtmEntry 0x%x, Status 0x%x\n",
  3237. pAtmEntry, pMcAtmEntry, Status));
  3238. AAMCDEBUGPATMADDR(AAD_EXTRA_LOUD, "McMakeCall Addr: ", &pMcAtmEntry->ATMAddress);
  3239. if (Status == NDIS_STATUS_SUCCESS)
  3240. {
  3241. pMcAtmInfo->ActiveLeaves++;
  3242. //
  3243. // Update Multicast state
  3244. //
  3245. AA_SET_FLAG(pMcAtmInfo->Flags,
  3246. AA_IPMC_AI_CONN_STATE_MASK,
  3247. AA_IPMC_AI_CONN_ACTIVE);
  3248. //
  3249. // Update state of "first party"
  3250. //
  3251. pMcAtmEntry->NdisPartyHandle = NdisPartyHandle;
  3252. AA_SET_FLAG(pMcAtmEntry->Flags,
  3253. AA_IPMC_AE_CONN_STATE_MASK,
  3254. AA_IPMC_AE_CONN_ACTIVE);
  3255. bWantConnUpdate = TRUE;
  3256. //
  3257. // If we had decided to terminate this member when the
  3258. // MakeCall was going on, then we now mark this as Invalid.
  3259. // When we next update this PMP connection, this member will
  3260. // be removed.
  3261. //
  3262. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  3263. AA_IPMC_AE_GEN_STATE_MASK,
  3264. AA_IPMC_AE_TERMINATING))
  3265. {
  3266. AA_SET_FLAG(pMcAtmEntry->Flags,
  3267. AA_IPMC_AE_GEN_STATE_MASK,
  3268. AA_IPMC_AE_INVALID);
  3269. }
  3270. }
  3271. else
  3272. {
  3273. //
  3274. // A PMP call failed. If the failure is not "transient",
  3275. // we remove the member we were trying to connect to
  3276. // from the list. If there is atleast one more member
  3277. // that hasn't been attempted yet, try to connect to that.
  3278. //
  3279. AAMCDEBUGP(AAD_INFO, ("McMakeCall failed: pAtmEntry 0x%x, pMcAtmEntry 0x%x, Status 0x%x ",
  3280. pAtmEntry, pMcAtmEntry, Status));
  3281. AAMCDEBUGPATMADDR(AAD_INFO, " Addr: ", &pMcAtmEntry->ATMAddress);
  3282. //
  3283. // Update PMP connection state
  3284. //
  3285. AA_SET_FLAG(pAtmEntry->pMcAtmInfo->Flags,
  3286. AA_IPMC_AI_CONN_STATE_MASK,
  3287. AA_IPMC_AI_CONN_NONE);
  3288. if (AA_IS_TRANSIENT_FAILURE(Status))
  3289. {
  3290. //
  3291. // Update first party state.
  3292. //
  3293. AA_SET_FLAG(pMcAtmEntry->Flags,
  3294. AA_IPMC_AE_CONN_STATE_MASK,
  3295. AA_IPMC_AE_CONN_TEMP_FAILURE);
  3296. DelayBeforeRetry = AA_GET_TIMER_DURATION(&(pMcAtmEntry->Timer));
  3297. if (DelayBeforeRetry == 0)
  3298. {
  3299. //
  3300. // First time we're doing this.
  3301. //
  3302. DelayBeforeRetry = AA_GET_RANDOM(
  3303. pInterface->MinPartyRetryDelay,
  3304. pInterface->MaxPartyRetryDelay);
  3305. }
  3306. else
  3307. {
  3308. DelayBeforeRetry = 2*DelayBeforeRetry;
  3309. }
  3310. AtmArpStartTimer(
  3311. pInterface,
  3312. &(pMcAtmEntry->Timer),
  3313. AtmArpMcPartyRetryDelayTimeout,
  3314. DelayBeforeRetry,
  3315. (PVOID)pMcAtmEntry
  3316. );
  3317. }
  3318. else
  3319. {
  3320. AA_SET_FLAG(pMcAtmEntry->Flags,
  3321. AA_IPMC_AE_CONN_STATE_MASK,
  3322. AA_IPMC_AE_CONN_DISCONNECTED);
  3323. AtmArpMcUnlinkAtmMember(
  3324. pAtmEntry,
  3325. pMcAtmEntry
  3326. );
  3327. }
  3328. //
  3329. // Look for a member that we haven't tried to connect to.
  3330. //
  3331. for (ppMcAtmEntry = &(pMcAtmInfo->pMcAtmEntryList);
  3332. *ppMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY;
  3333. ppMcAtmEntry = &((*ppMcAtmEntry)->pNextMcAtmEntry))
  3334. {
  3335. if (AA_IS_FLAG_SET((*ppMcAtmEntry)->Flags,
  3336. AA_IPMC_AE_CONN_STATE_MASK,
  3337. AA_IPMC_AE_CONN_DISCONNECTED))
  3338. {
  3339. //
  3340. // Found one.
  3341. //
  3342. break;
  3343. }
  3344. }
  3345. if (*ppMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY)
  3346. {
  3347. pMcAtmEntry = *ppMcAtmEntry;
  3348. //
  3349. // Move this member to the top of the list.
  3350. // First, unlink from current position.
  3351. //
  3352. *ppMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
  3353. //
  3354. // Now insert this at top of list.
  3355. //
  3356. pMcAtmEntry->pNextMcAtmEntry = pMcAtmInfo->pMcAtmEntryList;
  3357. pMcAtmInfo->pMcAtmEntryList = pMcAtmEntry;
  3358. bWantConnUpdate = TRUE;
  3359. }
  3360. else
  3361. {
  3362. //
  3363. // There is no ATM member that we haven't tried to connect to.
  3364. //
  3365. if (pMcAtmInfo->pMcAtmEntryList == NULL_PATMARP_IPMC_ATM_ENTRY)
  3366. {
  3367. //
  3368. // The list of ATM Members is empty.
  3369. //
  3370. AA_RELEASE_AE_LOCK(pAtmEntry);
  3371. AA_ACQUIRE_IE_LOCK(pIpEntry);
  3372. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  3373. AtmArpAbortIPEntry(pIpEntry);
  3374. //
  3375. // IE Lock is released within the above.
  3376. //
  3377. bAtmEntryLockAcquired = FALSE;
  3378. }
  3379. }
  3380. }
  3381. if (bWantConnUpdate)
  3382. {
  3383. AA_ASSERT(bAtmEntryLockAcquired == TRUE);
  3384. AtmArpMcUpdateConnection(pAtmEntry);
  3385. //
  3386. // AE Lock is released within the above.
  3387. //
  3388. }
  3389. else
  3390. {
  3391. if (bAtmEntryLockAcquired)
  3392. {
  3393. AA_RELEASE_AE_LOCK(pAtmEntry);
  3394. }
  3395. }
  3396. }
  3397. #endif // IPMCAST
  3398. VOID
  3399. AtmArpCloseCallCompleteHandler(
  3400. IN NDIS_STATUS Status,
  3401. IN NDIS_HANDLE ProtocolVcContext,
  3402. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
  3403. )
  3404. /*++
  3405. Routine Description:
  3406. This routine handles completion of a previous NdisClCloseCall.
  3407. It is assumed that Status is always NDIS_STATUS_SUCCESS.
  3408. We delete the VC on which the call was just closed.
  3409. Special case: if we just finished closing a PMP call for a multicast
  3410. group that has been told to migrate to a (possibly) new set of
  3411. addresses, start off a new connection now.
  3412. Arguments:
  3413. Status - Status of the Close Call.
  3414. ProtocolVcContext - Pointer to ATMARP VC structure.
  3415. ProtocolPartyContext - Not used.
  3416. Return Value:
  3417. None
  3418. --*/
  3419. {
  3420. PATMARP_VC pVc;
  3421. PATMARP_VC * ppVc;
  3422. PATMARP_ATM_ENTRY pAtmEntry;
  3423. PATMARP_INTERFACE pInterface;
  3424. #ifdef IPMCAST
  3425. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry; // represents the last leaf
  3426. PATMARP_IPMC_ATM_INFO pMcAtmInfo;
  3427. #endif // IPMCAST
  3428. ULONG rc; // Ref Count
  3429. NDIS_HANDLE NdisVcHandle;
  3430. BOOLEAN UpdatePMPConnection;
  3431. BOOLEAN AtmEntryIsClosing;
  3432. BOOLEAN IsMarsProblem;
  3433. BOOLEAN IsPVC;
  3434. BOOLEAN Found;
  3435. pVc = (PATMARP_VC)ProtocolVcContext;
  3436. AA_STRUCT_ASSERT(pVc, avc);
  3437. AADEBUGP(AAD_VERY_LOUD, ("CloseCallComplete: pVc 0x%x, Flags 0x%x, RefCount %d\n",
  3438. pVc, pVc->Flags, pVc->RefCount));
  3439. IsPVC = AA_IS_FLAG_SET(pVc->Flags, AA_VC_TYPE_MASK, AA_VC_TYPE_PVC);
  3440. //
  3441. // This VC may not be linked to an ATM Entry, e.g. for an unresolved
  3442. // Incoming PVC.
  3443. //
  3444. pAtmEntry = pVc->pAtmEntry;
  3445. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  3446. {
  3447. AtmEntryIsClosing = AA_IS_FLAG_SET(pAtmEntry->Flags,
  3448. AA_ATM_ENTRY_STATE_MASK,
  3449. AA_ATM_ENTRY_CLOSING);
  3450. }
  3451. else
  3452. {
  3453. AtmEntryIsClosing = FALSE;
  3454. }
  3455. pInterface = pVc->pInterface;
  3456. if (IsPVC)
  3457. {
  3458. //
  3459. // Take the PVC out of the unresolved VC list, if it
  3460. // exists there.
  3461. //
  3462. Found = FALSE;
  3463. AA_ACQUIRE_IF_LOCK(pInterface);
  3464. ppVc = &(pInterface->pUnresolvedVcs);
  3465. while (*ppVc != NULL_PATMARP_VC)
  3466. {
  3467. if (*ppVc == pVc)
  3468. {
  3469. *ppVc = pVc->pNextVc;
  3470. Found = TRUE;
  3471. break;
  3472. }
  3473. ppVc = &((*ppVc)->pNextVc);
  3474. }
  3475. AA_RELEASE_IF_LOCK(pInterface);
  3476. AA_ACQUIRE_VC_LOCK(pVc);
  3477. if (Found)
  3478. {
  3479. AADEBUGP(AAD_FATAL,
  3480. ("CloseCallComplete: took VC (PVC) %x out of IF %x\n",
  3481. pVc, pInterface));
  3482. rc = AtmArpDereferenceVc(pVc); // Unresolved VC list
  3483. }
  3484. else
  3485. {
  3486. rc = pVc->RefCount;
  3487. }
  3488. if (rc == 0)
  3489. {
  3490. //
  3491. // The VC is gone!
  3492. //
  3493. AADEBUGP(AAD_WARNING,
  3494. ("CloseCallComplete: VC (PVC) %x derefed away, IF %x\n",
  3495. pVc, pInterface));
  3496. return;
  3497. }
  3498. else
  3499. {
  3500. AA_RELEASE_VC_LOCK(pVc);
  3501. }
  3502. }
  3503. #ifdef IPMCAST
  3504. //
  3505. // We have lost our connection to the MARS if this was the last
  3506. // VC going to that address. We should atleast be a party on
  3507. // ClusterControlVc.
  3508. //
  3509. IsMarsProblem = FALSE;
  3510. if (pInterface->AdminState == IF_STATUS_UP)
  3511. {
  3512. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  3513. {
  3514. if (pAtmEntry->pVcList->pNextVc == NULL_PATMARP_VC)
  3515. {
  3516. if (pInterface->pCurrentMARS &&
  3517. (pInterface->pCurrentMARS->pAtmEntry == pAtmEntry))
  3518. {
  3519. IsMarsProblem = TRUE;
  3520. AA_ACQUIRE_IF_LOCK(pInterface);
  3521. AtmArpReferenceInterface(pInterface);
  3522. AA_RELEASE_IF_LOCK(pInterface);
  3523. }
  3524. }
  3525. }
  3526. }
  3527. UpdatePMPConnection = FALSE;
  3528. pMcAtmEntry = (PATMARP_IPMC_ATM_ENTRY)ProtocolPartyContext;
  3529. //
  3530. // If this is a point-to-multipoint connection that was closed,
  3531. // handle unlinking the last leaf.
  3532. //
  3533. if (pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY)
  3534. {
  3535. //
  3536. // This is a PMP connection.
  3537. //
  3538. AAMCDEBUGP(AAD_LOUD, ("CloseCallComplete (MC): pAtmEntry 0x%x/0x%x\n",
  3539. pAtmEntry, pAtmEntry->Flags));
  3540. AA_ASSERT(pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  3541. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3542. AA_SET_FLAG(pMcAtmEntry->Flags,
  3543. AA_IPMC_AE_CONN_STATE_MASK,
  3544. AA_IPMC_AE_CONN_DISCONNECTED);
  3545. AtmArpMcUnlinkAtmMember(pAtmEntry, pMcAtmEntry);
  3546. pMcAtmInfo = pAtmEntry->pMcAtmInfo;
  3547. AA_ASSERT(pMcAtmInfo != NULL_PATMARP_IPMC_ATM_INFO);
  3548. //
  3549. // Make the new list of ATM stations (the "Migrate to" list)
  3550. // the current list. This might be NULL.
  3551. //
  3552. pMcAtmInfo->pMcAtmEntryList = pMcAtmInfo->pMcAtmMigrateList;
  3553. pMcAtmInfo->pMcAtmMigrateList = NULL_PATMARP_IPMC_ATM_ENTRY;
  3554. //
  3555. // If there is a non-empty migrate list, then we have
  3556. // to make a fresh PMP connection.
  3557. //
  3558. UpdatePMPConnection =
  3559. (pMcAtmInfo->pMcAtmEntryList != NULL_PATMARP_IPMC_ATM_ENTRY);
  3560. AA_SET_FLAG(pMcAtmInfo->Flags,
  3561. AA_IPMC_AI_CONN_STATE_MASK,
  3562. AA_IPMC_AI_CONN_NONE);
  3563. AA_RELEASE_AE_LOCK(pAtmEntry);
  3564. }
  3565. #endif // IPMCAST
  3566. AA_ACQUIRE_VC_LOCK(pVc);
  3567. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  3568. {
  3569. AtmArpUnlinkVcFromAtmEntry(pVc, TRUE);
  3570. rc = AtmArpDereferenceVc(pVc); // ATM Entry ref
  3571. AA_ASSERT(rc != 0);
  3572. }
  3573. rc = AtmArpDereferenceVc(pVc); // Call reference
  3574. AA_ASSERT(rc != 0); // CreateVc reference remains
  3575. AA_SET_FLAG(pVc->Flags,
  3576. AA_VC_CALL_STATE_MASK,
  3577. AA_VC_CALL_STATE_IDLE);
  3578. AA_ASSERT(pVc->PacketList == NULL);
  3579. //
  3580. // If this VC belongs to us, delete it.
  3581. //
  3582. if (AA_IS_FLAG_SET(pVc->Flags,
  3583. AA_VC_OWNER_MASK,
  3584. AA_VC_OWNER_IS_ATMARP))
  3585. {
  3586. NdisVcHandle = pVc->NdisVcHandle;
  3587. rc = AtmArpDereferenceVc(pVc); // Create Vc ref
  3588. if (rc != 0)
  3589. {
  3590. // Could still be temp refs...
  3591. AA_RELEASE_VC_LOCK(pVc);
  3592. }
  3593. else
  3594. {
  3595. // The VC has been deallocated, and lock released
  3596. }
  3597. #ifndef VC_REFS_ON_SENDS
  3598. //
  3599. // Delete the NDIS association
  3600. //
  3601. (VOID)NdisCoDeleteVc(NdisVcHandle);
  3602. #endif // VC_REFS_ON_SENDS
  3603. AADEBUGP(AAD_LOUD,
  3604. ("CloseCallComplete: deleted NDIS VC on pVc 0x%x: NdisVcHandle 0x%x\n",
  3605. pVc, NdisVcHandle));
  3606. }
  3607. else
  3608. {
  3609. //
  3610. // VC belongs to the Call Manager -- take it back to the
  3611. // state it was when it was just created (via our CreateVcHandler).
  3612. // The Call Manager can either re-use it or delete it.
  3613. //
  3614. pVc->Flags = AA_VC_OWNER_IS_CALLMGR;
  3615. AA_RELEASE_VC_LOCK(pVc);
  3616. }
  3617. #ifdef IPMCAST
  3618. if (UpdatePMPConnection)
  3619. {
  3620. AAMCDEBUGP(AAD_INFO,
  3621. ("CloseCallComplete: pVc 0x%x, starting update on pAtmEntry 0x%x\n",
  3622. pVc, pAtmEntry));
  3623. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3624. AtmArpMcUpdateConnection(pAtmEntry);
  3625. //
  3626. // AE Lock is released within the above.
  3627. //
  3628. }
  3629. else
  3630. {
  3631. //
  3632. // If this was a PMP connection, handle the case
  3633. // of a remote-initiated CloseCall: we need to
  3634. // unlink the ATM Entry from the IP Entry.
  3635. //
  3636. if ((pMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY) &&
  3637. !AtmEntryIsClosing)
  3638. {
  3639. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3640. AtmArpInvalidateAtmEntry(pAtmEntry, FALSE); // CloseCallComplete
  3641. }
  3642. }
  3643. if (IsMarsProblem)
  3644. {
  3645. AA_ACQUIRE_IF_LOCK(pInterface);
  3646. rc = AtmArpDereferenceInterface(pInterface);
  3647. if (rc != 0)
  3648. {
  3649. AA_RELEASE_IF_LOCK(pInterface);
  3650. AtmArpMcHandleMARSFailure(pInterface, FALSE);
  3651. }
  3652. //
  3653. // else the interface is gone.
  3654. //
  3655. }
  3656. #endif
  3657. return;
  3658. }
  3659. #ifdef IPMCAST
  3660. VOID
  3661. AtmArpAddPartyCompleteHandler(
  3662. IN NDIS_STATUS Status,
  3663. IN NDIS_HANDLE ProtocolPartyContext,
  3664. IN NDIS_HANDLE NdisPartyHandle,
  3665. IN PCO_CALL_PARAMETERS pCallParameters
  3666. )
  3667. /*++
  3668. Routine Description:
  3669. This routine is called on completion of a previous call to
  3670. NdisClAddParty. Since we don't use point-to-multipoint connections,
  3671. this should never get called.
  3672. If the AddParty was successful, we just update state and exit. If it
  3673. failed, we check the failure code. If this indicates a transient
  3674. failure condition, we start a timer so that we reattempt to add this
  3675. party later. Otherwise ("hard" failure), this multicast entry is deleted.
  3676. Arguments:
  3677. Status - Status of the AddParty
  3678. ProtocolPartyContext - Pointer to an IPMC_ATM_ENTRY structure
  3679. NdisPartyHandle - NDIS' handle for this party
  3680. pCallParameters - what we had passed to NdisClAddParty
  3681. Return Value:
  3682. None
  3683. --*/
  3684. {
  3685. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  3686. PATMARP_ATM_ENTRY pAtmEntry;
  3687. PATMARP_IP_ENTRY pIpEntry;
  3688. PATMARP_VC pVc;
  3689. ULONG VcFlags;
  3690. PATMARP_INTERFACE pInterface;
  3691. ULONG DelayBeforeRetry;
  3692. BOOLEAN ClearToSend;
  3693. pMcAtmEntry = (PATMARP_IPMC_ATM_ENTRY)(ProtocolPartyContext);
  3694. AA_STRUCT_ASSERT(pMcAtmEntry, ame);
  3695. pAtmEntry = pMcAtmEntry->pAtmEntry;
  3696. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3697. pAtmEntry->pMcAtmInfo->TransientLeaves--;
  3698. pVc = pAtmEntry->pVcList;
  3699. VcFlags = pVc->Flags;
  3700. pInterface = pAtmEntry->pInterface;
  3701. AAMCDEBUGP(AAD_LOUD,
  3702. ("AddPartyComplete: Status 0x%x, pAtmEntry 0x%x, pMcAtmEntry 0x%x, pVc 0x%x\n",
  3703. Status, pAtmEntry, pMcAtmEntry, pVc));
  3704. AAMCDEBUGPATMADDR(AAD_EXTRA_LOUD, "AddParty Addr: ", &pMcAtmEntry->ATMAddress);
  3705. if (Status == NDIS_STATUS_SUCCESS)
  3706. {
  3707. AA_SET_FLAG(pMcAtmEntry->Flags,
  3708. AA_IPMC_AE_CONN_STATE_MASK,
  3709. AA_IPMC_AE_CONN_ACTIVE);
  3710. //
  3711. // If we had decided to terminate this member when the
  3712. // AddParty was going on, then we now mark this as Invalid.
  3713. // When we next update this PMP connection, this member will
  3714. // be removed.
  3715. //
  3716. if (AA_IS_FLAG_SET(pMcAtmEntry->Flags,
  3717. AA_IPMC_AE_GEN_STATE_MASK,
  3718. AA_IPMC_AE_TERMINATING))
  3719. {
  3720. AA_SET_FLAG(pMcAtmEntry->Flags,
  3721. AA_IPMC_AE_GEN_STATE_MASK,
  3722. AA_IPMC_AE_INVALID);
  3723. }
  3724. pMcAtmEntry->NdisPartyHandle = NdisPartyHandle;
  3725. pAtmEntry->pMcAtmInfo->ActiveLeaves++;
  3726. }
  3727. else
  3728. {
  3729. AAMCDEBUGP(AAD_INFO,
  3730. ("AddPartyComplete: Status 0x%x, pAtmEntry 0x%x, to ", Status, pAtmEntry));
  3731. AAMCDEBUGPATMADDR(AAD_INFO, "", &pMcAtmEntry->ATMAddress);
  3732. //
  3733. // Check if the failure was due to a transient
  3734. // condition.
  3735. //
  3736. if (AA_IS_TRANSIENT_FAILURE(Status))
  3737. {
  3738. //
  3739. // We'll fire a timer, so that we reattempt to
  3740. // connect to this one later. If we had already
  3741. // done this (i.e. time out on failure), then
  3742. // we include a back-off time in the delay.
  3743. //
  3744. DelayBeforeRetry = AA_GET_TIMER_DURATION(&(pMcAtmEntry->Timer));
  3745. if (DelayBeforeRetry == 0)
  3746. {
  3747. //
  3748. // First time we're doing this.
  3749. //
  3750. DelayBeforeRetry = AA_GET_RANDOM(
  3751. pInterface->MinPartyRetryDelay,
  3752. pInterface->MaxPartyRetryDelay);
  3753. }
  3754. else
  3755. {
  3756. DelayBeforeRetry = 2*DelayBeforeRetry;
  3757. }
  3758. AtmArpStartTimer(
  3759. pInterface,
  3760. &(pMcAtmEntry->Timer),
  3761. AtmArpMcPartyRetryDelayTimeout,
  3762. DelayBeforeRetry,
  3763. (PVOID)pMcAtmEntry
  3764. );
  3765. AA_SET_FLAG(pMcAtmEntry->Flags,
  3766. AA_IPMC_AE_CONN_STATE_MASK,
  3767. AA_IPMC_AE_CONN_TEMP_FAILURE);
  3768. }
  3769. else
  3770. {
  3771. //
  3772. // Not a transient failure. Delete this member.
  3773. //
  3774. AA_SET_FLAG(pMcAtmEntry->Flags,
  3775. AA_IPMC_AE_CONN_STATE_MASK,
  3776. AA_IPMC_AE_CONN_DISCONNECTED);
  3777. AtmArpMcUnlinkAtmMember(
  3778. pAtmEntry,
  3779. pMcAtmEntry
  3780. );
  3781. }
  3782. }
  3783. ClearToSend = ((pAtmEntry->pMcAtmInfo->TransientLeaves == 0) &&
  3784. (AA_IS_FLAG_SET(pAtmEntry->pMcAtmInfo->Flags,
  3785. AA_IPMC_AI_CONN_STATE_MASK,
  3786. AA_IPMC_AI_CONN_ACTIVE)));
  3787. pIpEntry = pAtmEntry->pIpEntryList;
  3788. AA_RELEASE_AE_LOCK(pAtmEntry);
  3789. if (pCallParameters != (PCO_CALL_PARAMETERS)NULL)
  3790. {
  3791. AA_FREE_MEM(pCallParameters);
  3792. }
  3793. //
  3794. // Check if the VC is closing, and we had held back because
  3795. // this AddParty was in progress. If so, try to continue the
  3796. // CloseCall process.
  3797. //
  3798. AA_ACQUIRE_VC_LOCK(pVc);
  3799. if (AA_IS_FLAG_SET(pVc->Flags,
  3800. AA_VC_CLOSE_STATE_MASK,
  3801. AA_VC_CLOSE_STATE_CLOSING))
  3802. {
  3803. AtmArpCloseCall(pVc);
  3804. //
  3805. // VC Lock is released within the above.
  3806. //
  3807. }
  3808. else
  3809. {
  3810. PNDIS_PACKET pPacketList;
  3811. AA_RELEASE_VC_LOCK(pVc);
  3812. if (ClearToSend && pIpEntry)
  3813. {
  3814. AA_ACQUIRE_IE_LOCK(pIpEntry);
  3815. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  3816. pPacketList = pIpEntry->PacketList;
  3817. pIpEntry->PacketList = (PNDIS_PACKET)NULL;
  3818. AA_RELEASE_IE_LOCK(pIpEntry);
  3819. if (pPacketList != (PNDIS_PACKET)NULL)
  3820. {
  3821. AAMCDEBUGP(AAD_INFO, ("AddPtyCompl: pAtmEntry 0x%x, sending pktlist 0x%x\n",
  3822. pAtmEntry, pPacketList));
  3823. AtmArpSendPacketListOnAtmEntry(
  3824. pInterface,
  3825. pAtmEntry,
  3826. pPacketList,
  3827. TRUE // IsBroadcast
  3828. );
  3829. }
  3830. }
  3831. }
  3832. }
  3833. #else
  3834. VOID
  3835. AtmArpAddPartyCompleteHandler(
  3836. IN NDIS_STATUS Status,
  3837. IN NDIS_HANDLE ProtocolPartyContext,
  3838. IN NDIS_HANDLE NdisPartyHandle,
  3839. IN PCO_CALL_PARAMETERS pCallParameters
  3840. )
  3841. /*++
  3842. Routine Description:
  3843. This routine is called on completion of a previous call to
  3844. NdisClAddParty. Since we don't use point-to-multipoint connections,
  3845. this should never get called.
  3846. Arguments:
  3847. <Don't care>
  3848. Return Value:
  3849. None
  3850. --*/
  3851. {
  3852. AADEBUGP(AAD_ERROR, ("Add Party Complete unexpectedly called\n"));
  3853. AA_ASSERT(FALSE);
  3854. }
  3855. #endif // IPMCAST
  3856. VOID
  3857. AtmArpDropPartyCompleteHandler(
  3858. IN NDIS_STATUS Status,
  3859. IN NDIS_HANDLE ProtocolPartyContext
  3860. )
  3861. /*++
  3862. Routine Description:
  3863. This routine is called on completion of a previous call to
  3864. NdisClDropParty. We unlink our party structure and free it.
  3865. Arguments:
  3866. Status - Final result of the Drop Party
  3867. ProtocolPartyContext - Pointer to the MC ATM Entry we used
  3868. to represent the party.
  3869. Return Value:
  3870. None
  3871. --*/
  3872. {
  3873. #ifdef IPMCAST
  3874. PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
  3875. PATMARP_ATM_ENTRY pAtmEntry;
  3876. PATMARP_IP_ENTRY pIpEntry;
  3877. ULONG rc;
  3878. BOOLEAN LockReleased;
  3879. AAMCDEBUGP(AAD_LOUD, ("DropPartyComplete: Status 0x%x, Context 0x%x\n",
  3880. Status, ProtocolPartyContext));
  3881. AA_ASSERT(Status == NDIS_STATUS_SUCCESS);
  3882. pMcAtmEntry = (PATMARP_IPMC_ATM_ENTRY)ProtocolPartyContext;
  3883. AA_STRUCT_ASSERT(pMcAtmEntry, ame);
  3884. pAtmEntry = pMcAtmEntry->pAtmEntry;
  3885. AA_ASSERT(pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  3886. AA_STRUCT_ASSERT(pAtmEntry, aae);
  3887. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  3888. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP); // temp ref
  3889. AA_SET_FLAG(pMcAtmEntry->Flags,
  3890. AA_IPMC_AE_CONN_STATE_MASK,
  3891. AA_IPMC_AE_CONN_DISCONNECTED);
  3892. AtmArpMcUnlinkAtmMember(pAtmEntry, pMcAtmEntry);
  3893. //
  3894. // If we are in the processing of closing this PMP call,
  3895. // and this event signifies that all preliminary DropParty's
  3896. // are complete, then close the call itself.
  3897. //
  3898. LockReleased = FALSE;
  3899. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP); // temp ref
  3900. if (rc != 0)
  3901. {
  3902. PATMARP_VC pVc;
  3903. pVc = pAtmEntry->pVcList;
  3904. if (pVc != NULL_PATMARP_VC)
  3905. {
  3906. if (AA_IS_FLAG_SET(pVc->Flags,
  3907. AA_VC_CLOSE_STATE_MASK,
  3908. AA_VC_CLOSE_STATE_CLOSING) &&
  3909. (pAtmEntry->pMcAtmInfo->NumOfEntries == 1))
  3910. {
  3911. AA_RELEASE_AE_LOCK(pAtmEntry);
  3912. AA_ACQUIRE_VC_LOCK(pVc);
  3913. AtmArpCloseCall(pVc);
  3914. //
  3915. // VC lock is released within the above.
  3916. //
  3917. LockReleased = TRUE;
  3918. }
  3919. }
  3920. }
  3921. if (!LockReleased)
  3922. {
  3923. AA_RELEASE_AE_LOCK(pAtmEntry);
  3924. }
  3925. #endif // IPMCAST
  3926. }
  3927. VOID
  3928. AtmArpModifyQosCompleteHandler(
  3929. IN NDIS_STATUS Status,
  3930. IN NDIS_HANDLE ProtocolVcContext,
  3931. IN PCO_CALL_PARAMETERS pCallParameters
  3932. )
  3933. /*++
  3934. Routine Description:
  3935. This routine is called on completion of a previous call to
  3936. NdisClModifyCallQoS. Since we don't call this, this should never
  3937. get called.
  3938. Arguments:
  3939. <Don't care>
  3940. Return Value:
  3941. None
  3942. --*/
  3943. {
  3944. AADEBUGP(AAD_ERROR, ("Modify QOS Complete unexpectedly called\n"));
  3945. AA_ASSERT(FALSE);
  3946. }
  3947. #ifndef OID_CO_AF_CLOSE
  3948. #define OID_CO_AF_CLOSE 0xFE00000A
  3949. #endif
  3950. NDIS_STATUS
  3951. AtmArpCoRequestHandler(
  3952. IN NDIS_HANDLE ProtocolAfContext,
  3953. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  3954. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  3955. IN OUT PNDIS_REQUEST pNdisRequest
  3956. )
  3957. /*++
  3958. Routine Description:
  3959. This routine is called by NDIS when our Call Manager sends us an
  3960. NDIS Request. NDIS Requests that are of significance to us are:
  3961. - OID_CO_ADDRESS_CHANGE
  3962. The set of addresses registered with the switch has changed,
  3963. i.e. address registration is complete. We issue an NDIS Request
  3964. ourselves to get the list of addresses registered.
  3965. - OID_CO_SIGNALING_ENABLED
  3966. We ignore this as of now.
  3967. - OID_CO_SIGNALING_DISABLED
  3968. We ignore this for now.
  3969. - OID_CO_AF_CLOSE
  3970. The Call Manager wants us to shut down this Interface.
  3971. We ignore all other OIDs.
  3972. Arguments:
  3973. ProtocolAfContext - Our context for the Address Family binding,
  3974. which is a pointer to the ATMARP Interface.
  3975. ProtocolVcContext - Our context for a VC, which is a pointer to
  3976. an ATMARP VC structure.
  3977. ProtocolPartyContext - Our context for a Party. Since we don't do
  3978. PMP, this is ignored (must be NULL).
  3979. pNdisRequest - Pointer to the NDIS Request.
  3980. Return Value:
  3981. NDIS_STATUS_SUCCESS if we recognized the OID
  3982. NDIS_STATUS_NOT_RECOGNIZED if we didn't.
  3983. --*/
  3984. {
  3985. PATMARP_INTERFACE pInterface;
  3986. NDIS_STATUS Status;
  3987. pInterface = (PATMARP_INTERFACE)ProtocolAfContext;
  3988. AA_STRUCT_ASSERT(pInterface, aai);
  3989. //
  3990. // Initialize
  3991. //
  3992. Status = NDIS_STATUS_NOT_RECOGNIZED;
  3993. if (pNdisRequest->RequestType == NdisRequestSetInformation)
  3994. {
  3995. switch (pNdisRequest->DATA.SET_INFORMATION.Oid)
  3996. {
  3997. case OID_CO_ADDRESS_CHANGE:
  3998. //
  3999. // The Call Manager says that the list of addresses
  4000. // registered on this interface has changed. Get the
  4001. // (potentially) new ATM address for this interface.
  4002. //
  4003. AA_ACQUIRE_IF_LOCK(pInterface);
  4004. pInterface->AtmInterfaceUp = FALSE;
  4005. AA_RELEASE_IF_LOCK(pInterface);
  4006. AtmArpGetAtmAddress(pInterface);
  4007. Status = NDIS_STATUS_SUCCESS;
  4008. break;
  4009. case OID_CO_SIGNALING_ENABLED: // FALLTHRU
  4010. case OID_CO_SIGNALING_DISABLED:
  4011. // Ignored for now
  4012. Status = NDIS_STATUS_SUCCESS;
  4013. break;
  4014. case OID_CO_AF_CLOSE:
  4015. AA_ACQUIRE_IF_LOCK(pInterface);
  4016. pInterface->AdminState = pInterface->State = IF_STATUS_DOWN;
  4017. pInterface->LastChangeTime = GetTimeTicks();
  4018. AA_RELEASE_IF_LOCK(pInterface);
  4019. AtmArpShutdownInterface(pInterface);
  4020. Status = NDIS_STATUS_SUCCESS;
  4021. break;
  4022. default:
  4023. break;
  4024. }
  4025. }
  4026. return (Status);
  4027. }
  4028. VOID
  4029. AtmArpCoRequestCompleteHandler(
  4030. IN NDIS_STATUS Status,
  4031. IN NDIS_HANDLE ProtocolAfContext,
  4032. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  4033. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  4034. IN PNDIS_REQUEST pNdisRequest
  4035. )
  4036. /*++
  4037. Routine Description:
  4038. This routine is called by NDIS when a previous call to NdisCoRequest
  4039. that had pended, is complete. We handle this based on the request
  4040. we had sent, which has to be one of:
  4041. - OID_CO_GET_ADDRESSES
  4042. Get all addresses registered on the specified AF binding.
  4043. Arguments:
  4044. Status - Status of the Request.
  4045. ProtocolAfContext - Our context for the Address Family binding,
  4046. which is a pointer to the ATMARP Interface.
  4047. ProtocolVcContext - Our context for a VC, which is a pointer to
  4048. an ATMARP VC structure.
  4049. ProtocolPartyContext - Our context for a Party. Since we don't do
  4050. PMP, this is ignored (must be NULL).
  4051. pNdisRequest - Pointer to the NDIS Request.
  4052. Return Value:
  4053. None
  4054. --*/
  4055. {
  4056. PATMARP_INTERFACE pInterface;
  4057. ULONG Oid;
  4058. pInterface = (PATMARP_INTERFACE)ProtocolAfContext;
  4059. AA_STRUCT_ASSERT(pInterface, aai);
  4060. if (pNdisRequest->RequestType == NdisRequestQueryInformation)
  4061. {
  4062. switch (pNdisRequest->DATA.QUERY_INFORMATION.Oid)
  4063. {
  4064. case OID_CO_GET_ADDRESSES:
  4065. AtmArpHandleGetAddressesComplete(
  4066. Status,
  4067. pInterface,
  4068. pNdisRequest
  4069. );
  4070. break;
  4071. default:
  4072. AADEBUGP(AAD_ERROR,
  4073. ("CoRequestComplete: pNdisReq 0x%x, unknown Query Oid 0x%x\n",
  4074. pNdisRequest,
  4075. pNdisRequest->DATA.QUERY_INFORMATION.Oid));
  4076. AA_ASSERT(FALSE);
  4077. break;
  4078. }
  4079. }
  4080. else
  4081. {
  4082. Oid = pNdisRequest->DATA.QUERY_INFORMATION.Oid;
  4083. switch (Oid)
  4084. {
  4085. case OID_CO_ADD_ADDRESS: // FALLTHRU
  4086. case OID_CO_DELETE_ADDRESS:
  4087. AtmArpHandleModAddressComplete(
  4088. Status,
  4089. pInterface,
  4090. pNdisRequest,
  4091. Oid
  4092. );
  4093. break;
  4094. default:
  4095. AADEBUGP(AAD_ERROR,
  4096. ("CoRequestComplete: pNdisReq 0x%x, unknown Set Oid 0x%x\n",
  4097. pNdisRequest, Oid));
  4098. AA_ASSERT(FALSE);
  4099. break;
  4100. }
  4101. }
  4102. AA_FREE_MEM(pNdisRequest);
  4103. }
  4104. VOID
  4105. AtmArpGetAtmAddress(
  4106. IN PATMARP_INTERFACE pInterface
  4107. )
  4108. /*++
  4109. Routine Description:
  4110. Send a request to the Call Manager to retrieve the ATM address
  4111. registered with the switch on the given interface.
  4112. This is called when the Call Manager tells us that there has been
  4113. a change in its list of addresses registered with the switch.
  4114. Normally, this happens when we start up our signalling stack (i.e.
  4115. initial address registration), but it might happen during runtime,
  4116. for example, if the link goes down and up, or we get physically
  4117. connected to a different switch...
  4118. In any case, we issue an NDIS Request to the Call Manager to retrieve
  4119. the first address it has registered. Action then continues in
  4120. AtmArpHandleGetAddressesComplete.
  4121. Arguments:
  4122. pInterface - Interface structure for which this event occurred.
  4123. Return Value:
  4124. None
  4125. --*/
  4126. {
  4127. PNDIS_REQUEST pNdisRequest;
  4128. NDIS_HANDLE NdisAfHandle;
  4129. NDIS_HANDLE NdisAdapterHandle;
  4130. NDIS_STATUS Status;
  4131. PCO_ADDRESS_LIST pAddressList;
  4132. ULONG RequestSize;
  4133. AADEBUGP(AAD_INFO, ("GetAtmAddress: pIf 0x%x\n", pInterface));
  4134. AA_ACQUIRE_IF_LOCK(pInterface);
  4135. NdisAfHandle = pInterface->NdisAfHandle;
  4136. NdisAdapterHandle = pInterface->NdisAdapterHandle;
  4137. AA_RELEASE_IF_LOCK(pInterface);
  4138. RequestSize = sizeof(CO_ADDRESS_LIST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  4139. //
  4140. // Allocate all that we need.
  4141. //
  4142. AA_ALLOC_MEM(pNdisRequest, NDIS_REQUEST, sizeof(NDIS_REQUEST)+RequestSize);
  4143. if (pNdisRequest != (PNDIS_REQUEST)NULL)
  4144. {
  4145. pAddressList = (PCO_ADDRESS_LIST)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
  4146. AA_SET_MEM(pAddressList, 0, sizeof(CO_ADDRESS_LIST));
  4147. Status = AtmArpSendNdisCoRequest(
  4148. NdisAdapterHandle,
  4149. NdisAfHandle,
  4150. pNdisRequest,
  4151. NdisRequestQueryInformation,
  4152. OID_CO_GET_ADDRESSES,
  4153. (PVOID)pAddressList,
  4154. RequestSize
  4155. );
  4156. if (Status != NDIS_STATUS_PENDING)
  4157. {
  4158. AtmArpCoRequestCompleteHandler(
  4159. Status,
  4160. (NDIS_HANDLE)pInterface, // ProtocolAfContext
  4161. NULL, // Vc Context
  4162. NULL, // Party Context
  4163. pNdisRequest
  4164. );
  4165. }
  4166. }
  4167. }
  4168. VOID
  4169. AtmArpHandleGetAddressesComplete(
  4170. IN NDIS_STATUS Status,
  4171. IN PATMARP_INTERFACE pInterface,
  4172. IN PNDIS_REQUEST pNdisRequest
  4173. )
  4174. /*++
  4175. Routine Description:
  4176. This is called when we have a reply to our previous call to
  4177. NdisCoRequest(OID_CO_GET_ADDRESSES). Check if we got any addresses
  4178. back: if we did, store the address as our Local ATM Address, and
  4179. if conditions are ripe, start registering ourselves with the ARP
  4180. server.
  4181. Since we allocated the NDIS request, free it here.
  4182. Arguments:
  4183. Status - result of the request
  4184. pInterface - ATMARP interface on which the request was issued
  4185. pNdisRequest - the request itself. This will also contain the
  4186. returned address.
  4187. Return Value:
  4188. None
  4189. --*/
  4190. {
  4191. PCO_ADDRESS_LIST pAddressList;
  4192. ATM_ADDRESS UNALIGNED * pAtmAddress;
  4193. AADEBUGP(AAD_LOUD, ("GetAddr complete: pIf 0x%x, Status 0x%x\n",
  4194. pInterface, Status));
  4195. if (Status == NDIS_STATUS_SUCCESS)
  4196. {
  4197. pAddressList = (PCO_ADDRESS_LIST)
  4198. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  4199. AADEBUGP(AAD_LOUD, ("GetAddr complete: pIf 0x%x, Count %d\n",
  4200. pInterface, pAddressList->NumberOfAddresses));
  4201. if (pAddressList->NumberOfAddresses > 0)
  4202. {
  4203. //
  4204. // We have atleast one address here. Copy it in.
  4205. //
  4206. AA_ACQUIRE_IF_LOCK(pInterface);
  4207. pAtmAddress = (ATM_ADDRESS UNALIGNED *)(pAddressList->AddressList.Address);
  4208. AA_COPY_MEM((PUCHAR)&(pInterface->LocalAtmAddress),
  4209. (PUCHAR)pAtmAddress,
  4210. sizeof(ATM_ADDRESS));
  4211. //
  4212. // Patch the selector byte with whatever is configured for
  4213. // this LIS.
  4214. //
  4215. pInterface->LocalAtmAddress.Address[ATM_ADDRESS_LENGTH-1] =
  4216. (UCHAR)(pInterface->SapSelector);
  4217. pInterface->AtmInterfaceUp = TRUE;
  4218. //
  4219. // To force registration:
  4220. //
  4221. AA_SET_FLAG(
  4222. pInterface->Flags,
  4223. AA_IF_SERVER_STATE_MASK,
  4224. AA_IF_SERVER_NO_CONTACT);
  4225. AtmArpStartRegistration(pInterface);
  4226. //
  4227. // The IF lock is released within the above.
  4228. //
  4229. #ifdef IPMCAST
  4230. //
  4231. // Attempt to start our Multicast side, too.
  4232. //
  4233. AA_ACQUIRE_IF_LOCK(pInterface);
  4234. AtmArpMcStartRegistration(pInterface);
  4235. //
  4236. // IF Lock is released within the above.
  4237. //
  4238. #endif // IPMCAST
  4239. //
  4240. // Add any (additional) addresses we want to register with
  4241. // the switch now.
  4242. //
  4243. AtmArpUpdateAddresses(
  4244. pInterface,
  4245. TRUE // Add them
  4246. );
  4247. }
  4248. //
  4249. // else no address is registered currently.
  4250. //
  4251. }
  4252. //
  4253. // else our request failed! Wait for another ADDRESS_CHANGE.
  4254. //
  4255. return;
  4256. }
  4257. VOID
  4258. AtmArpUpdateAddresses(
  4259. IN PATMARP_INTERFACE pInterface,
  4260. IN BOOLEAN AddThem
  4261. )
  4262. /*++
  4263. Routine Description:
  4264. Update the list of addresses we want the Call manager to register
  4265. with the switch: either add addresses or delete them. We do this
  4266. only if we are running in an SVC environment.
  4267. Arguments:
  4268. pInterface - Pointer to ATMARP Interface
  4269. AddThem - TRUE if caller wants us to add addresses,
  4270. FALSE if caller wats us to delete them.
  4271. Return Value:
  4272. None
  4273. --*/
  4274. {
  4275. PATMARP_SAP pAtmArpSap;
  4276. PATMARP_SAP pNextSap;
  4277. PATM_SAP pAtmSap;
  4278. PATM_ADDRESS pAtmAddress;
  4279. PCO_ADDRESS pCoAddress;
  4280. PNDIS_REQUEST pNdisRequest;
  4281. NDIS_HANDLE NdisAfHandle;
  4282. NDIS_HANDLE NdisAdapterHandle;
  4283. NDIS_OID Oid;
  4284. ULONG BufferLength;
  4285. NDIS_STATUS Status;
  4286. BOOLEAN StateIsOkay; // Does the current state allow this request
  4287. ULONG rc; // Ref count
  4288. StateIsOkay = TRUE;
  4289. BufferLength = sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  4290. AA_ACQUIRE_IF_LOCK(pInterface);
  4291. NdisAfHandle = pInterface->NdisAfHandle;
  4292. NdisAdapterHandle = pInterface->NdisAdapterHandle;
  4293. if (AddThem)
  4294. {
  4295. Oid = OID_CO_ADD_ADDRESS;
  4296. //
  4297. // This is allowed only if the AdminState for the interface
  4298. // is UP.
  4299. //
  4300. if (pInterface->AdminState != IF_STATUS_UP)
  4301. {
  4302. StateIsOkay = FALSE;
  4303. }
  4304. }
  4305. else
  4306. {
  4307. Oid = OID_CO_DELETE_ADDRESS;
  4308. }
  4309. //
  4310. // Check all pre-conditions before progressing.
  4311. //
  4312. if (!(pInterface->PVCOnly) &&
  4313. (StateIsOkay) &&
  4314. (pInterface->AtmInterfaceUp) &&
  4315. (pInterface->NumberOfSaps > 1))
  4316. {
  4317. AA_ASSERT(pInterface->SapList.pNextSap != NULL_PATMARP_SAP);
  4318. //
  4319. // Reference the Interface so that it doesn't go away.
  4320. //
  4321. AtmArpReferenceInterface(pInterface);
  4322. pAtmArpSap = pInterface->SapList.pNextSap;
  4323. AA_RELEASE_IF_LOCK(pInterface);
  4324. do
  4325. {
  4326. if (AA_IS_FLAG_SET(
  4327. pAtmArpSap->Flags,
  4328. AA_SAP_ADDRTYPE_MASK,
  4329. AA_SAP_ADDRTYPE_NEED_ADD))
  4330. {
  4331. //
  4332. // This SAP is of the type that needs to be added/deleted
  4333. // via ILMI
  4334. //
  4335. AA_ALLOC_MEM(
  4336. pNdisRequest,
  4337. NDIS_REQUEST,
  4338. sizeof(NDIS_REQUEST)+
  4339. sizeof(CO_ADDRESS)+
  4340. sizeof(ATM_ADDRESS)
  4341. );
  4342. if (pNdisRequest != (PNDIS_REQUEST)NULL)
  4343. {
  4344. AA_SET_MEM(pNdisRequest, 0, sizeof(NDIS_REQUEST));
  4345. //
  4346. // Stuff in our context for this request, which is a pointer
  4347. // to this ATMARP SAP, into the ProtocolReserved part of
  4348. // this request, so that we can handle completion easily.
  4349. //
  4350. *((PVOID *)(pNdisRequest->ProtocolReserved)) = (PVOID)pAtmArpSap;
  4351. pCoAddress = (PCO_ADDRESS)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
  4352. pCoAddress->AddressSize = sizeof(ATM_ADDRESS);
  4353. BufferLength = sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  4354. //
  4355. // Save a pointer to the next SAP
  4356. //
  4357. pNextSap = pAtmArpSap->pNextSap;
  4358. //
  4359. // Get at the ATM address in this SAP.
  4360. //
  4361. pAtmSap = (PATM_SAP)(pAtmArpSap->pInfo->Sap);
  4362. AA_ASSERT(pAtmSap->NumberOfAddresses > 0);
  4363. pAtmAddress = (PATM_ADDRESS)(pAtmSap->Addresses);
  4364. AA_COPY_MEM(pCoAddress->Address, pAtmAddress, sizeof(ATM_ADDRESS));
  4365. Status = AtmArpSendNdisCoRequest(
  4366. NdisAdapterHandle,
  4367. NdisAfHandle,
  4368. pNdisRequest,
  4369. NdisRequestSetInformation,
  4370. Oid,
  4371. (PVOID)pCoAddress,
  4372. BufferLength
  4373. );
  4374. //
  4375. // Go to the next SAP in the list.
  4376. //
  4377. pAtmArpSap = pNextSap;
  4378. }
  4379. else
  4380. {
  4381. //
  4382. // Out of resources.
  4383. //
  4384. break;
  4385. }
  4386. }
  4387. }
  4388. while (pAtmArpSap != NULL_PATMARP_SAP);
  4389. //
  4390. // Remove the reference we added earlier on.
  4391. //
  4392. AA_ACQUIRE_IF_LOCK(pInterface);
  4393. rc = AtmArpDereferenceInterface(pInterface);
  4394. if (rc > 0)
  4395. {
  4396. AA_RELEASE_IF_LOCK(pInterface);
  4397. }
  4398. //
  4399. // else the Interface is gone!
  4400. }
  4401. else
  4402. {
  4403. AA_RELEASE_IF_LOCK(pInterface);
  4404. }
  4405. }
  4406. VOID
  4407. AtmArpHandleModAddressComplete(
  4408. IN NDIS_STATUS Status,
  4409. IN PATMARP_INTERFACE pInterface,
  4410. IN PNDIS_REQUEST pNdisRequest,
  4411. IN ULONG Oid
  4412. )
  4413. /*++
  4414. Routine Description:
  4415. This is called when we have a reply to our previous call to
  4416. NdisCoRequest(OID_CO_ADD_ADDRESS or OID_CO_DELETE_ADDRESS).
  4417. All we do now is to update the state on the ATMARP SAP.
  4418. Arguments:
  4419. Status - the result of our request.
  4420. pInterface - ATMARP interface pointer.
  4421. pNdisRequest - the request we had sent.
  4422. Oid - CO_OID_ADD_ADDRESS or CO_OID_DELETE_ADDRESS
  4423. Return Value:
  4424. None
  4425. --*/
  4426. {
  4427. PATMARP_SAP pAtmArpSap;
  4428. pAtmArpSap = (PATMARP_SAP)(*((PVOID *)(pNdisRequest->ProtocolReserved)));
  4429. AA_STRUCT_ASSERT(pAtmArpSap, aas);
  4430. AA_ACQUIRE_IF_LOCK(pInterface);
  4431. //
  4432. // Update the state on this ATMARP SAP.
  4433. //
  4434. if ((Oid == OID_CO_ADD_ADDRESS) && (Status == NDIS_STATUS_SUCCESS))
  4435. {
  4436. AA_SET_FLAG(pAtmArpSap->Flags,
  4437. AA_SAP_ILMI_STATE_MASK,
  4438. AA_SAP_ILMI_STATE_ADDED);
  4439. }
  4440. else
  4441. {
  4442. AA_SET_FLAG(pAtmArpSap->Flags,
  4443. AA_SAP_ILMI_STATE_MASK,
  4444. AA_SAP_ILMI_STATE_IDLE);
  4445. }
  4446. AA_RELEASE_IF_LOCK(pInterface);
  4447. }
  4448. NDIS_STATUS
  4449. AtmArpSendNdisCoRequest(
  4450. IN NDIS_HANDLE NdisAdapterHandle,
  4451. IN NDIS_HANDLE NdisAfHandle,
  4452. IN PNDIS_REQUEST pNdisRequest,
  4453. IN NDIS_REQUEST_TYPE RequestType,
  4454. IN NDIS_OID Oid,
  4455. IN PVOID pBuffer,
  4456. IN ULONG BufferLength
  4457. )
  4458. /*++
  4459. Routine Description:
  4460. Send an NDIS Connection Oriented request to the Call Manager. We
  4461. allocate an NDIS_REQUEST structure, link the supplied buffer to it,
  4462. and send the request. If the request does not pend, we call our
  4463. completion routine from here.
  4464. Arguments:
  4465. NdisAdapterHandle - Binding Handle to be used in the request
  4466. NdisAfHandle - AF Handle value to be used in the request
  4467. pNdisRequest - Pointer to NDIS request structure
  4468. RequestType - Set/Query information
  4469. Oid - OID to be passed in the request
  4470. pBuffer - place for value(s)
  4471. BufferLength - length of above
  4472. Return Value:
  4473. Status of the NdisCoRequest.
  4474. --*/
  4475. {
  4476. NDIS_STATUS Status;
  4477. //
  4478. // Fill in the NDIS Request structure
  4479. //
  4480. pNdisRequest->RequestType = RequestType;
  4481. if (RequestType == NdisRequestQueryInformation)
  4482. {
  4483. pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  4484. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
  4485. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
  4486. pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
  4487. pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
  4488. }
  4489. else
  4490. {
  4491. pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
  4492. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
  4493. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
  4494. pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  4495. pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  4496. }
  4497. Status = NdisCoRequest(
  4498. NdisAdapterHandle,
  4499. NdisAfHandle,
  4500. NULL, // No VC handle
  4501. NULL, // No Party Handle
  4502. pNdisRequest);
  4503. return (Status);
  4504. }