Source code of Windows XP (NT5)
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.

3766 lines
85 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. callmgr.c
  6. Abstract:
  7. Call Manager interface routines.
  8. Author:
  9. Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. //
  17. // Rounded-off size of generic Q.2931 IE header
  18. //
  19. #define SIZEOF_Q2931_IE ROUND_OFF(sizeof(Q2931_IE))
  20. #define SIZEOF_AAL_PARAMETERS_IE ROUND_OFF(sizeof(AAL_PARAMETERS_IE))
  21. #define SIZEOF_ATM_TRAFFIC_DESCR_IE ROUND_OFF(sizeof(ATM_TRAFFIC_DESCRIPTOR_IE))
  22. #define SIZEOF_ATM_BBC_IE ROUND_OFF(sizeof(ATM_BROADBAND_BEARER_CAPABILITY_IE))
  23. #define SIZEOF_ATM_BLLI_IE ROUND_OFF(sizeof(ATM_BLLI_IE))
  24. #define SIZEOF_ATM_QOS_IE ROUND_OFF(sizeof(ATM_QOS_CLASS_IE))
  25. //
  26. // Total space required for Information Elements in an outgoing call.
  27. //
  28. #define ATMLANE_CALL_IE_SPACE ( \
  29. SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE + \
  30. SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE + \
  31. SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE + \
  32. SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE + \
  33. SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE )
  34. //
  35. // Size of Call Manager Parameters Block
  36. //
  37. #define ATMLANE_Q2931_CALLMGR_PARAMETERS_SIZE \
  38. sizeof(Q2931_CALLMGR_PARAMETERS) - 1 + \
  39. sizeof(Q2931_IE) - 1 + \
  40. sizeof(AAL_PARAMETERS_IE) + \
  41. sizeof(Q2931_IE) - 1 + \
  42. sizeof(ATM_TRAFFIC_DESCRIPTOR_IE) + \
  43. sizeof(Q2931_IE) - 1 + \
  44. sizeof(ATM_BROADBAND_BEARER_CAPABILITY_IE) + \
  45. sizeof(Q2931_IE) - 1 + \
  46. sizeof(ATM_BLLI_IE) + \
  47. sizeof(Q2931_IE) - 1 + \
  48. sizeof(ATM_QOS_CLASS_IE)
  49. //
  50. // ATMLANE Call Manager Parameters Block
  51. //
  52. typedef struct _ATMLANE_Q2931_CALLMGR_PARAMETERS
  53. {
  54. UCHAR Q2931CallMgrParameters[ATMLANE_Q2931_CALLMGR_PARAMETERS_SIZE];
  55. }
  56. ATMLANE_Q2931_CALLMGR_PARAMETERS,
  57. *PATMLANE_Q2931_CALLMGR_PARAMETERS;
  58. VOID
  59. AtmLaneAfRegisterNotifyHandler(
  60. IN NDIS_HANDLE ProtocolBindingContext,
  61. IN PCO_ADDRESS_FAMILY pAddressFamily
  62. )
  63. /*++
  64. Routine Description:
  65. This routine is called by NDIS when a Call manager registers its support
  66. for an Address Family over an adapter. If this is the Address Family we
  67. are interested in (UNI 3.1), then we bootstrap the Elans for this adapter.
  68. Arguments:
  69. ProtocolBindingContext - our context passed in NdisOpenAdapter, which is
  70. a pointer to our Adapter structure.
  71. pAddressFamily - points to a structure describing the Address Family
  72. being registered by a Call Manager.
  73. Return Value:
  74. None
  75. --*/
  76. {
  77. PATMLANE_ADAPTER pAdapter;
  78. #if DEBUG_IRQL
  79. KIRQL EntryIrql;
  80. #endif
  81. GET_ENTRY_IRQL(EntryIrql);
  82. TRACEIN(AfRegisterNotifyHandler);
  83. do
  84. {
  85. DBGP((1, "AfRegisterNotifyHandler: AF %x MajVer %x MinVer %x\n",
  86. pAddressFamily->AddressFamily,
  87. pAddressFamily->MajorVersion,
  88. pAddressFamily->MinorVersion));
  89. //
  90. // Only interested in UNI Version 3.1
  91. //
  92. if ((pAddressFamily->AddressFamily != CO_ADDRESS_FAMILY_Q2931) ||
  93. (pAddressFamily->MajorVersion != 3) ||
  94. (pAddressFamily->MinorVersion != 1))
  95. {
  96. DBGP((2, "AfRegisterNotifyHandler: ignoring AF %x MajVer %x MinVer %x\n",
  97. pAddressFamily->AddressFamily,
  98. pAddressFamily->MajorVersion,
  99. pAddressFamily->MinorVersion));
  100. break;
  101. }
  102. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  103. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  104. ACQUIRE_ADAPTER_LOCK(pAdapter);
  105. pAdapter->Flags |= ADAPTER_FLAGS_AF_NOTIFIED;
  106. while (pAdapter->Flags & ADAPTER_FLAGS_OPEN_IN_PROGRESS)
  107. {
  108. RELEASE_ADAPTER_LOCK(pAdapter);
  109. DBGP((0, "AfRegisterNotifyHandler: Adapter %p/%x still opening\n",
  110. pAdapter, pAdapter->Flags));
  111. (VOID)WAIT_ON_BLOCK_STRUCT(&pAdapter->OpenBlock);
  112. ACQUIRE_ADAPTER_LOCK(pAdapter);
  113. }
  114. RELEASE_ADAPTER_LOCK(pAdapter);
  115. //
  116. // Bootstrap the ELANs configured on this adapter
  117. //
  118. AtmLaneBootStrapElans(pAdapter);
  119. } while (FALSE);
  120. TRACEOUT(AfFRegisterNotifyHandler);
  121. CHECK_EXIT_IRQL(EntryIrql);
  122. return;
  123. }
  124. NDIS_STATUS
  125. AtmLaneOpenCallMgr(
  126. IN PATMLANE_ELAN pElan
  127. )
  128. /*++
  129. Routine Description:
  130. Start access to the Call Manager on an Elan,
  131. by doing the following:
  132. - Open Address Family
  133. For all of these, we wait for completion in case they pend.
  134. It is assumed that the Elan structure is locked.
  135. Arguments:
  136. pElan - pointer to the ATMLANE Elan
  137. Return Value:
  138. NDIS status.
  139. --*/
  140. {
  141. PCO_ADDRESS_FAMILY pAddressFamily;
  142. NDIS_STATUS Status;
  143. ULONG RequestSize;
  144. NDIS_CLIENT_CHARACTERISTICS AtmLaneClientChars;
  145. TRACEIN(OpenCallMgr);
  146. pAddressFamily = (PCO_ADDRESS_FAMILY)NULL;
  147. Status = NDIS_STATUS_SUCCESS;
  148. do {
  149. //
  150. // Allocate address family struct.
  151. //
  152. ALLOC_MEM(&pAddressFamily, sizeof(CO_ADDRESS_FAMILY));
  153. if ((PCO_ADDRESS_FAMILY)NULL == pAddressFamily)
  154. {
  155. DBGP((0, "OpenCallMgr: Alloc address family struct failed\n"));
  156. break;
  157. }
  158. //
  159. // Init the address family struct.
  160. //
  161. NdisZeroMemory(pAddressFamily, sizeof(CO_ADDRESS_FAMILY));
  162. pAddressFamily->AddressFamily = CO_ADDRESS_FAMILY_Q2931;
  163. pAddressFamily->MajorVersion = 3;
  164. pAddressFamily->MinorVersion = 1;
  165. //
  166. // Init the call manager client characteristics.
  167. //
  168. NdisZeroMemory(&AtmLaneClientChars, sizeof(AtmLaneClientChars));
  169. AtmLaneClientChars.MajorVersion = 5;
  170. AtmLaneClientChars.MinorVersion = 0;
  171. AtmLaneClientChars.ClCreateVcHandler = AtmLaneCreateVcHandler;
  172. AtmLaneClientChars.ClDeleteVcHandler = AtmLaneDeleteVcHandler;
  173. AtmLaneClientChars.ClRequestHandler = AtmLaneCoRequestHandler;
  174. AtmLaneClientChars.ClRequestCompleteHandler = AtmLaneCoRequestCompleteHandler;
  175. AtmLaneClientChars.ClOpenAfCompleteHandler = AtmLaneOpenAfCompleteHandler;
  176. AtmLaneClientChars.ClCloseAfCompleteHandler = AtmLaneCloseAfCompleteHandler;
  177. AtmLaneClientChars.ClRegisterSapCompleteHandler = AtmLaneRegisterSapCompleteHandler;
  178. AtmLaneClientChars.ClDeregisterSapCompleteHandler = AtmLaneDeregisterSapCompleteHandler;
  179. AtmLaneClientChars.ClMakeCallCompleteHandler = AtmLaneMakeCallCompleteHandler;
  180. AtmLaneClientChars.ClModifyCallQoSCompleteHandler = AtmLaneModifyQosCompleteHandler;
  181. AtmLaneClientChars.ClCloseCallCompleteHandler = AtmLaneCloseCallCompleteHandler;
  182. AtmLaneClientChars.ClAddPartyCompleteHandler = AtmLaneAddPartyCompleteHandler;
  183. AtmLaneClientChars.ClDropPartyCompleteHandler = AtmLaneDropPartyCompleteHandler;
  184. AtmLaneClientChars.ClIncomingCallHandler = AtmLaneIncomingCallHandler;
  185. AtmLaneClientChars.ClIncomingCallQoSChangeHandler = (CL_INCOMING_CALL_QOS_CHANGE_HANDLER)NULL;
  186. AtmLaneClientChars.ClIncomingCloseCallHandler = AtmLaneIncomingCloseHandler;
  187. AtmLaneClientChars.ClIncomingDropPartyHandler = AtmLaneIncomingDropPartyHandler;
  188. AtmLaneClientChars.ClCallConnectedHandler = AtmLaneCallConnectedHandler;
  189. //
  190. // Open the call manager
  191. //
  192. INIT_BLOCK_STRUCT(&pElan->Block);
  193. Status = NdisClOpenAddressFamily(
  194. pElan->NdisAdapterHandle,
  195. pAddressFamily,
  196. pElan,
  197. &AtmLaneClientChars,
  198. sizeof(AtmLaneClientChars),
  199. &pElan->NdisAfHandle);
  200. if (NDIS_STATUS_PENDING == Status)
  201. {
  202. //
  203. // Wait for completion
  204. //
  205. Status = WAIT_ON_BLOCK_STRUCT(&pElan->Block);
  206. }
  207. if (NDIS_STATUS_SUCCESS != Status)
  208. {
  209. DBGP((0, "%d OpenCallMgr: OpenAddressFamily failed, status %x, Elan %x\n",
  210. pElan->ElanNumber, Status, pElan));
  211. break;
  212. }
  213. break;
  214. }
  215. while (FALSE);
  216. //
  217. // clean up.
  218. if (pAddressFamily != (PCO_ADDRESS_FAMILY)NULL)
  219. {
  220. NdisFreeMemory(pAddressFamily,0,0);
  221. }
  222. TRACEOUT(OpenCallMgr);
  223. return (Status);
  224. }
  225. VOID
  226. AtmLaneOpenAfCompleteHandler(
  227. IN NDIS_STATUS Status,
  228. IN NDIS_HANDLE ProtocolAfContext,
  229. IN NDIS_HANDLE NdisAfHandle
  230. )
  231. /*++
  232. Routine Description:
  233. This handler is called to indicate completion of a previous call
  234. to NdisClOpenAddressFamily. We would have blocked the thread that
  235. called this. Wake it up now.
  236. If open is successful, store NdisAfHandle in Adapter.
  237. We don't need to acquire locks here because the thread that called
  238. OpenAddressFamily would have blocked with a lock acquired.
  239. Arguments:
  240. Status - Status of the Open AF
  241. ProtocolAfContext - Pointer to our Adapter structure
  242. NdisAfHandle - NDIS handle to the AF association
  243. Return Value:
  244. None
  245. --*/
  246. {
  247. PATMLANE_ELAN pElan;
  248. #if DEBUG_IRQL
  249. KIRQL EntryIrql;
  250. #endif
  251. GET_ENTRY_IRQL(EntryIrql);
  252. TRACEIN(OpenAfCompleteHandler);
  253. pElan = (PATMLANE_ELAN)ProtocolAfContext;
  254. STRUCT_ASSERT(pElan, atmlane_elan);
  255. if (NDIS_STATUS_SUCCESS == Status)
  256. {
  257. pElan->NdisAfHandle = NdisAfHandle;
  258. }
  259. //
  260. // Store status, Wake up the blocked thread.
  261. //
  262. SIGNAL_BLOCK_STRUCT(&pElan->Block, Status);
  263. TRACEOUT(OpenAfCompleteHandler);
  264. CHECK_EXIT_IRQL(EntryIrql);
  265. return;
  266. }
  267. VOID
  268. AtmLaneCloseAfCompleteHandler(
  269. IN NDIS_STATUS Status,
  270. IN NDIS_HANDLE ProtocolAfContext
  271. )
  272. /*++
  273. Routine Description:
  274. This handler is called to indicate completion of a previous call
  275. to NdisClCloseAddressFamily. We would have blocked the thread that
  276. called this. Wake it up now.
  277. We don't need to acquire locks here because the thread that called
  278. CloseAddressFamily would have blocked with a lock acquired.
  279. Arguments:
  280. Status - Status of the Open AF
  281. ProtocolAfContext - Pointer to our Adapter structure
  282. Return Value:
  283. None
  284. --*/
  285. {
  286. PATMLANE_ELAN pElan;
  287. #if DEBUG_IRQL
  288. KIRQL EntryIrql;
  289. #endif
  290. GET_ENTRY_IRQL(EntryIrql);
  291. TRACEIN(CloseAfCompleteHandler);
  292. pElan = (PATMLANE_ELAN)ProtocolAfContext;
  293. STRUCT_ASSERT(pElan, atmlane_elan);
  294. DBGP((0, "%d CloseAF complete on Elan %x sts %x\n", pElan->ElanNumber, pElan, Status));
  295. AtmLaneContinueShutdownElan(pElan);
  296. TRACEOUT(CloseAfCompleteHandler);
  297. CHECK_EXIT_IRQL(EntryIrql);
  298. return;
  299. }
  300. VOID
  301. AtmLaneRegisterSaps(
  302. IN PATMLANE_ELAN pElan LOCKIN NOLOCKOUT
  303. )
  304. /*++
  305. Routine Description:
  306. Register the LANE SAPs for the given Elan.
  307. We just issue the NdisClRegisterSap requests for all SAPs.
  308. We don't wait for completion.
  309. Arguments:
  310. pElan - Pointer to ATMLANE Elan.
  311. Return Value:
  312. None
  313. --*/
  314. {
  315. PATMLANE_SAP pAtmLaneLesSap;
  316. PATMLANE_SAP pAtmLaneBusSap;
  317. PATMLANE_SAP pAtmLaneDataSap;
  318. PATM_ADDRESS pAtmAddress;
  319. PATM_SAP pAtmSap;
  320. NDIS_STATUS Status;
  321. ULONG rc; // Ref count on Elan
  322. ATM_BLLI_IE UNALIGNED * pBlli;
  323. ATM_BHLI_IE UNALIGNED * pBhli;
  324. TRACEIN(RegisterSaps);
  325. if (pElan->AdminState != ELAN_STATE_OPERATIONAL)
  326. {
  327. RELEASE_ELAN_LOCK(pElan);
  328. return;
  329. }
  330. //
  331. // Initialize SAPs
  332. //
  333. pElan->SapsRegistered = 0;
  334. pAtmLaneLesSap = &pElan->LesSap;
  335. pAtmLaneBusSap = &pElan->BusSap;
  336. pAtmLaneDataSap = &pElan->DataSap;
  337. //
  338. // First init the LES control distribute connection SAP
  339. //
  340. SET_FLAG(pAtmLaneLesSap->Flags,
  341. SAP_REG_STATE_MASK,
  342. SAP_REG_STATE_REGISTERING);
  343. pAtmLaneLesSap->LaneType = VC_LANE_TYPE_CONTROL_DISTRIBUTE;
  344. pAtmLaneLesSap->pElan = pElan;
  345. pAtmLaneLesSap->Flags = SAP_REG_STATE_IDLE;
  346. pAtmLaneLesSap->pInfo->SapType = SAP_TYPE_NSAP;
  347. pAtmLaneLesSap->pInfo->SapLength = sizeof(ATM_SAP)+sizeof(ATM_ADDRESS);
  348. pAtmSap = (PATM_SAP)&pAtmLaneLesSap->pInfo->Sap;
  349. pBhli = (ATM_BHLI_IE UNALIGNED *)&pAtmSap->Bhli;
  350. pBlli = (ATM_BLLI_IE UNALIGNED *)&pAtmSap->Blli;
  351. pBhli->HighLayerInfoType = SAP_FIELD_ABSENT;
  352. pBlli->Layer2Protocol = SAP_FIELD_ABSENT;
  353. pBlli->Layer3Protocol = BLLI_L3_ISO_TR9577;
  354. pBlli->Layer3IPI = BLLI_L3_IPI_SNAP;
  355. pBlli->SnapId[0] = 0x00;
  356. pBlli->SnapId[1] = 0xa0;
  357. pBlli->SnapId[2] = 0x3e;
  358. pBlli->SnapId[3] = 0x00;
  359. pBlli->SnapId[4] = 0x01; // control distribute
  360. pAtmSap->NumberOfAddresses = 1;
  361. pAtmAddress = (PATM_ADDRESS)pAtmSap->Addresses;
  362. pAtmAddress->AddressType = ATM_NSAP;
  363. pAtmAddress->NumberOfDigits = ATM_ADDRESS_LENGTH;
  364. NdisMoveMemory(
  365. pAtmAddress->Address,
  366. pElan->AtmAddress.Address,
  367. ATM_ADDRESS_LENGTH);
  368. //
  369. // Now init the BUS mulicast forward connection SAP
  370. //
  371. SET_FLAG(pAtmLaneBusSap->Flags,
  372. SAP_REG_STATE_MASK,
  373. SAP_REG_STATE_REGISTERING);
  374. pAtmLaneBusSap->LaneType = VC_LANE_TYPE_MULTI_FORWARD;
  375. pAtmLaneBusSap->pElan = pElan;
  376. pAtmLaneBusSap->Flags = SAP_REG_STATE_IDLE;
  377. pAtmLaneBusSap->pInfo->SapType = SAP_TYPE_NSAP;
  378. pAtmLaneBusSap->pInfo->SapLength = sizeof(ATM_SAP)+sizeof(ATM_ADDRESS);
  379. pAtmSap = (PATM_SAP)&pAtmLaneBusSap->pInfo->Sap;
  380. pBhli = (ATM_BHLI_IE UNALIGNED *)&pAtmSap->Bhli;
  381. pBlli = (ATM_BLLI_IE UNALIGNED *)&pAtmSap->Blli;
  382. pBhli->HighLayerInfoType = SAP_FIELD_ABSENT;
  383. pBlli->Layer2Protocol = SAP_FIELD_ABSENT;
  384. pBlli->Layer3Protocol = BLLI_L3_ISO_TR9577;
  385. pBlli->Layer3IPI = BLLI_L3_IPI_SNAP;
  386. pBlli->SnapId[0] = 0x00;
  387. pBlli->SnapId[1] = 0xa0;
  388. pBlli->SnapId[2] = 0x3e;
  389. pBlli->SnapId[3] = 0x00;
  390. if (pElan->LanType == LANE_LANTYPE_ETH)
  391. {
  392. pBlli->SnapId[4] = 0x04; // Ethernet/802.3 Multicast Forward
  393. }
  394. else
  395. {
  396. pBlli->SnapId[4] = 0x05; // 802.5 Multicast Forward
  397. }
  398. pAtmSap->NumberOfAddresses = 1;
  399. pAtmAddress = (PATM_ADDRESS)pAtmSap->Addresses;
  400. pAtmAddress->AddressType = ATM_NSAP;
  401. pAtmAddress->NumberOfDigits = ATM_ADDRESS_LENGTH;
  402. NdisMoveMemory(
  403. pAtmAddress->Address,
  404. pElan->AtmAddress.Address,
  405. ATM_ADDRESS_LENGTH);
  406. //
  407. // Now init the DATA direct connection SAP
  408. //
  409. SET_FLAG(pAtmLaneDataSap->Flags,
  410. SAP_REG_STATE_MASK,
  411. SAP_REG_STATE_REGISTERING);
  412. pAtmLaneDataSap->LaneType = VC_LANE_TYPE_DATA_DIRECT;
  413. pAtmLaneDataSap->pElan = pElan;
  414. pAtmLaneDataSap->Flags = SAP_REG_STATE_IDLE;
  415. pAtmLaneDataSap->pInfo->SapType = SAP_TYPE_NSAP;
  416. pAtmLaneDataSap->pInfo->SapLength = sizeof(ATM_SAP)+sizeof(ATM_ADDRESS);
  417. pAtmSap = (PATM_SAP)&pAtmLaneDataSap->pInfo->Sap;
  418. pBhli = (ATM_BHLI_IE UNALIGNED *)&pAtmSap->Bhli;
  419. pBlli = (ATM_BLLI_IE UNALIGNED *)&pAtmSap->Blli;
  420. pBhli->HighLayerInfoType = SAP_FIELD_ABSENT;
  421. pBlli->Layer2Protocol = SAP_FIELD_ABSENT;
  422. pBlli->Layer3Protocol = BLLI_L3_ISO_TR9577;
  423. pBlli->Layer3IPI = BLLI_L3_IPI_SNAP;
  424. pBlli->SnapId[0] = 0x00;
  425. pBlli->SnapId[1] = 0xa0;
  426. pBlli->SnapId[2] = 0x3e;
  427. pBlli->SnapId[3] = 0x00;
  428. if (pElan->LanType == LANE_LANTYPE_ETH)
  429. {
  430. pBlli->SnapId[4] = 0x02; // Ethernet/802.3 Data Direct
  431. }
  432. else
  433. {
  434. pBlli->SnapId[4] = 0x03; // 802.5 Data Direct
  435. }
  436. pAtmSap->NumberOfAddresses = 1;
  437. pAtmAddress = (PATM_ADDRESS)pAtmSap->Addresses;
  438. pAtmAddress->AddressType = ATM_NSAP;
  439. pAtmAddress->NumberOfDigits = ATM_ADDRESS_LENGTH;
  440. NdisMoveMemory(
  441. pAtmAddress->Address,
  442. pElan->AtmAddress.Address,
  443. ATM_ADDRESS_LENGTH);
  444. //
  445. // Make sure that the Elan doesn't go away.
  446. //
  447. AtmLaneReferenceElan(pElan, "tempregsaps");
  448. RELEASE_ELAN_LOCK(pElan);
  449. ASSERT(pElan->NdisAfHandle != NULL);
  450. //
  451. // Register the LES Sap
  452. //
  453. Status = NdisClRegisterSap(
  454. pElan->NdisAfHandle,
  455. (NDIS_HANDLE)pAtmLaneLesSap, // ProtocolSapContext
  456. pAtmLaneLesSap->pInfo,
  457. &(pAtmLaneLesSap->NdisSapHandle)
  458. );
  459. if (Status != NDIS_STATUS_PENDING)
  460. {
  461. AtmLaneRegisterSapCompleteHandler(
  462. Status,
  463. (NDIS_HANDLE)pAtmLaneLesSap,
  464. pAtmLaneLesSap->pInfo,
  465. pAtmLaneLesSap->NdisSapHandle
  466. );
  467. }
  468. ASSERT(pElan->NdisAfHandle != NULL);
  469. //
  470. // Register the BUS Sap
  471. //
  472. Status = NdisClRegisterSap(
  473. pElan->NdisAfHandle,
  474. (NDIS_HANDLE)pAtmLaneBusSap, // ProtocolSapContext
  475. pAtmLaneBusSap->pInfo,
  476. &(pAtmLaneBusSap->NdisSapHandle)
  477. );
  478. if (Status != NDIS_STATUS_PENDING)
  479. {
  480. AtmLaneRegisterSapCompleteHandler(
  481. Status,
  482. (NDIS_HANDLE)pAtmLaneBusSap,
  483. pAtmLaneBusSap->pInfo,
  484. pAtmLaneBusSap->NdisSapHandle
  485. );
  486. }
  487. ASSERT(pElan->NdisAfHandle != NULL);
  488. //
  489. // Register the DATA Sap
  490. //
  491. Status = NdisClRegisterSap(
  492. pElan->NdisAfHandle,
  493. (NDIS_HANDLE)pAtmLaneDataSap, // ProtocolSapContext
  494. pAtmLaneDataSap->pInfo,
  495. &(pAtmLaneDataSap->NdisSapHandle)
  496. );
  497. if (Status != NDIS_STATUS_PENDING)
  498. {
  499. AtmLaneRegisterSapCompleteHandler(
  500. Status,
  501. (NDIS_HANDLE)pAtmLaneDataSap,
  502. pAtmLaneDataSap->pInfo,
  503. pAtmLaneDataSap->NdisSapHandle
  504. );
  505. }
  506. //
  507. // Remove the reference we added earlier to the Elan.
  508. //
  509. ACQUIRE_ELAN_LOCK(pElan);
  510. rc = AtmLaneDereferenceElan(pElan, "tempregsaps");
  511. if (rc > 0)
  512. {
  513. RELEASE_ELAN_LOCK(pElan);
  514. }
  515. //
  516. // else the Elan is gone!
  517. TRACEOUT(RegisterSaps);
  518. return;
  519. }
  520. VOID
  521. AtmLaneDeregisterSaps(
  522. IN PATMLANE_ELAN pElan
  523. )
  524. /*++
  525. Routine Description:
  526. Deregister all SAPs on an ATMLANE Elan. We issue NdisClDeregisterSap
  527. calls on all SAPs we have currently registered.
  528. Arguments:
  529. pElan - Pointer to ATMLANE Elan
  530. Return Value:
  531. None
  532. --*/
  533. {
  534. NDIS_HANDLE NdisSapHandle;
  535. ULONG rc; // Reference count on Interface
  536. PATMLANE_SAP pAtmLaneSap;
  537. NDIS_STATUS Status;
  538. TRACEIN(DeregisterSaps);
  539. ACQUIRE_ELAN_LOCK(pElan);
  540. //
  541. // Make sure the Elan structure doesn't go away.
  542. //
  543. AtmLaneReferenceElan(pElan, "tempDeregSap");
  544. RELEASE_ELAN_LOCK(pElan);
  545. //
  546. // First the LES SAP
  547. //
  548. pAtmLaneSap = &(pElan->LesSap);
  549. NdisSapHandle = pAtmLaneSap->NdisSapHandle;
  550. if (NdisSapHandle != NULL)
  551. {
  552. Status = NdisClDeregisterSap(NdisSapHandle);
  553. if (Status != NDIS_STATUS_PENDING)
  554. {
  555. AtmLaneDeregisterSapCompleteHandler(
  556. Status,
  557. (NDIS_HANDLE)pAtmLaneSap
  558. );
  559. }
  560. }
  561. //
  562. // Then the BUS SAP
  563. //
  564. pAtmLaneSap = &(pElan->BusSap);
  565. NdisSapHandle = pAtmLaneSap->NdisSapHandle;
  566. if (NdisSapHandle != NULL)
  567. {
  568. Status = NdisClDeregisterSap(NdisSapHandle);
  569. if (Status != NDIS_STATUS_PENDING)
  570. {
  571. AtmLaneDeregisterSapCompleteHandler(
  572. Status,
  573. (NDIS_HANDLE)pAtmLaneSap
  574. );
  575. }
  576. }
  577. //
  578. // And finally the Data SAP
  579. //
  580. pAtmLaneSap = &(pElan->DataSap);
  581. NdisSapHandle = pAtmLaneSap->NdisSapHandle;
  582. if (NdisSapHandle != NULL)
  583. {
  584. Status = NdisClDeregisterSap(NdisSapHandle);
  585. if (Status != NDIS_STATUS_PENDING)
  586. {
  587. AtmLaneDeregisterSapCompleteHandler(
  588. Status,
  589. (NDIS_HANDLE)pAtmLaneSap
  590. );
  591. }
  592. }
  593. //
  594. // Remove the reference we added earlier to the Interface.
  595. //
  596. ACQUIRE_ELAN_LOCK(pElan);
  597. rc = AtmLaneDereferenceElan(pElan, "tempDeregSap");
  598. if (rc > 0)
  599. {
  600. RELEASE_ELAN_LOCK(pElan);
  601. }
  602. //
  603. // else the interface is gone
  604. //
  605. TRACEOUT(DeregisterSaps);
  606. return;
  607. }
  608. NDIS_STATUS
  609. AtmLaneMakeCall(
  610. IN PATMLANE_ELAN pElan,
  611. IN PATMLANE_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT,
  612. IN BOOLEAN UsePvc
  613. )
  614. /*++
  615. Routine Description:
  616. Place a call to the given destination.
  617. NOTE: The caller is assumed to hold a lock for the ATM Entry,
  618. which will be released here. The reason we do it this way is so that
  619. nobody else can come in and try to make another call (of the same kind)
  620. to this ATM Entry -- once we get a new VC into the ATM Entry's list,
  621. we can release its lock.
  622. SIDE EFFECT: If the NDIS call doesn't pend, then we call our
  623. MakeCall completion handler from here, and return NDIS_STATUS_PENDING
  624. to the caller.
  625. Arguments:
  626. pElan - the Elan originating this call
  627. pAtmEntry - Pointer to ATM Address Entry corresponding to the
  628. called address.
  629. Return Value:
  630. If there is an immediate failure (e.g. allocation failure), we return
  631. appropriate NDIS_STATUS value denoting that failure.
  632. If we made it to the call to NdisClMakeCall(), we return NDIS_STATUS_PENDING.
  633. However, if NDIS returns other than NDIS_STATUS_PENDING, we'd also
  634. call our MakeCall completion handler.
  635. --*/
  636. {
  637. PATMLANE_VC pVc;
  638. NDIS_STATUS Status;
  639. NDIS_HANDLE NdisVcHandle;
  640. NDIS_HANDLE NdisAfHandle;
  641. NDIS_HANDLE ProtocolVcContext;
  642. PCO_CALL_PARAMETERS pCallParameters;
  643. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  644. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  645. PCO_MEDIA_PARAMETERS pMediaParameters;
  646. PATM_MEDIA_PARAMETERS pAtmMediaParameters;
  647. Q2931_IE UNALIGNED * pIe;
  648. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  649. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  650. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  651. ATM_BLLI_IE UNALIGNED * pBlli;
  652. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  653. ULONG RequestSize;
  654. BOOLEAN bIsLockHeld;
  655. TRACEIN(MakeCall);
  656. STRUCT_ASSERT(pElan, atmlane_elan);
  657. STRUCT_ASSERT(pAtmEntry, atmlane_atm);
  658. bIsLockHeld = TRUE; // do we hold the ATM Entry lock?
  659. do
  660. {
  661. if (ELAN_STATE_OPERATIONAL != pElan->AdminState)
  662. {
  663. Status = NDIS_STATUS_FAILURE;
  664. break;
  665. }
  666. if (!UsePvc)
  667. {
  668. //
  669. // Default case is to make an server/peer SVC call.
  670. // Compute size of the SVC call parameters.
  671. //
  672. RequestSize = sizeof(CO_CALL_PARAMETERS) +
  673. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  674. sizeof(Q2931_CALLMGR_PARAMETERS) +
  675. ATMLANE_CALL_IE_SPACE;
  676. }
  677. else
  678. {
  679. //
  680. // This is the LECS PVC (vpi 0, vci 17).
  681. // Compute size of the PVC call parameters.
  682. //
  683. RequestSize = sizeof(CO_CALL_PARAMETERS) +
  684. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  685. sizeof(CO_MEDIA_PARAMETERS) +
  686. sizeof(ATM_MEDIA_PARAMETERS);
  687. }
  688. ALLOC_MEM(&pCallParameters, RequestSize);
  689. if ((PCO_CALL_PARAMETERS)NULL == pCallParameters)
  690. {
  691. DBGP((0, "MakeCall: callparams alloc (%d) failed\n", RequestSize));
  692. Status = NDIS_STATUS_RESOURCES;
  693. break;
  694. }
  695. //
  696. // Allocate a VC structure for the call
  697. //
  698. pVc = AtmLaneAllocateVc(pElan);
  699. if (NULL_PATMLANE_VC == pVc)
  700. {
  701. DBGP((0, "MakeCall: VC alloc failed\n"));
  702. FREE_MEM(pCallParameters);
  703. Status = NDIS_STATUS_RESOURCES;
  704. break;
  705. }
  706. //
  707. // For later call to MakeCallComplete
  708. //
  709. ProtocolVcContext = pVc;
  710. //
  711. // Get NDIS handle for this VC
  712. //
  713. NdisVcHandle = NULL_NDIS_HANDLE;
  714. NdisAfHandle = pElan->NdisAfHandle;
  715. if (NULL == NdisAfHandle)
  716. {
  717. DBGP((0, "%d MakeCall: ELAN %p: AfHandle is NULL!\n",
  718. pElan->ElanNumber, pElan));
  719. FREE_MEM(pCallParameters);
  720. Status = NDIS_STATUS_FAILURE;
  721. break;
  722. }
  723. Status = NdisCoCreateVc(
  724. pElan->NdisAdapterHandle,
  725. NdisAfHandle,
  726. ProtocolVcContext,
  727. &NdisVcHandle
  728. );
  729. if (NDIS_STATUS_SUCCESS != Status)
  730. {
  731. ASSERT(NDIS_STATUS_PENDING != Status);
  732. DBGP((0, "MakeCall: NdisCoCreateVc failed: %x, pAtmEnt %x, RefCount %d\n",
  733. Status, pAtmEntry, pAtmEntry->RefCount));
  734. FREE_MEM(pCallParameters);
  735. AtmLaneDeallocateVc(pVc);
  736. break;
  737. }
  738. DBGP((3, "MakeCall: pAtmEntry %x pVc %x NdisVcHandle %x\n",
  739. pAtmEntry,
  740. pVc,
  741. NdisVcHandle));
  742. AtmLaneReferenceVc(pVc, "vc"); // CreateVc reference
  743. //
  744. // Now fill in the rest of the VC structure. We don't need a lock
  745. // for the VC until it gets linked to the ATM Entry structure.
  746. //
  747. pVc->NdisVcHandle = NdisVcHandle;
  748. NdisMoveMemory((PUCHAR)&(pVc->CallingAtmAddress),
  749. (PUCHAR)&(pElan->AtmAddress),
  750. sizeof(ATM_ADDRESS));
  751. pVc->Flags = VC_TYPE_SVC |
  752. VC_OWNER_IS_ATMLANE |
  753. VC_CALL_STATE_OUTGOING_IN_PROGRESS;
  754. //
  755. // Start with with normal timeout,
  756. // AtmLaneLinkVcToAtmEntry will accelerate if necessary.
  757. //
  758. pVc->AgingTime = pElan->VccTimeout;
  759. switch (pAtmEntry->Type)
  760. {
  761. case ATM_ENTRY_TYPE_PEER:
  762. DBGP((1, "%d Outgoing call %x to PEER\n", pVc->pElan->ElanNumber, pVc));
  763. pVc->LaneType = VC_LANE_TYPE_DATA_DIRECT;
  764. break;
  765. case ATM_ENTRY_TYPE_LECS:
  766. DBGP((1, "%d Outgoing call %x to LECS\n", pVc->pElan->ElanNumber, pVc));
  767. pVc->LaneType = VC_LANE_TYPE_CONFIG_DIRECT;
  768. break;
  769. case ATM_ENTRY_TYPE_LES:
  770. DBGP((1, "%d Outgoing call %x to LES\n", pVc->pElan->ElanNumber, pVc));
  771. pVc->LaneType = VC_LANE_TYPE_CONTROL_DIRECT;
  772. break;
  773. case ATM_ENTRY_TYPE_BUS:
  774. DBGP((1, "%d Outgoing call %x to BUS\n", pVc->pElan->ElanNumber, pVc));
  775. pVc->LaneType = VC_LANE_TYPE_MULTI_SEND;
  776. break;
  777. default:
  778. ASSERT(FALSE);
  779. break;
  780. }
  781. //
  782. // Zero out call parameters.
  783. //
  784. NdisZeroMemory(pCallParameters, RequestSize);
  785. if (!UsePvc)
  786. {
  787. //
  788. // Distribute space and link up pointers amongst the various
  789. // structures for an SVC.
  790. //
  791. // pCallParameters------->+------------------------------------+
  792. // | CO_CALL_PARAMETERS |
  793. // pCallMgrParameters---->+------------------------------------+
  794. // | CO_CALL_MANAGER_PARAMETERS |
  795. // pAtmCallMgrParameters->+------------------------------------+
  796. // | Q2931_CALLMGR_PARAMETERS |
  797. // +------------------------------------+
  798. // | AAL_PARAMETERS_IE |
  799. // +------------------------------------+
  800. // | ATM_TRAFFIC_DESCRIPTOR_IE |
  801. // +------------------------------------+
  802. // | ATM_BROADBAND_BEARER_CAPABILITY_IE |
  803. // +------------------------------------+
  804. // | ATM_BLLI_IE |
  805. // +------------------------------------+
  806. // | ATM_QOS_CLASS_IE |
  807. // +------------------------------------+
  808. //
  809. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  810. ((PUCHAR)pCallParameters +
  811. sizeof(CO_CALL_PARAMETERS));
  812. pCallParameters->CallMgrParameters = pCallMgrParameters;
  813. pCallParameters->MediaParameters = (PCO_MEDIA_PARAMETERS)NULL;
  814. pCallMgrParameters->CallMgrSpecific.ParamType = CALLMGR_SPECIFIC_Q2931;
  815. pCallMgrParameters->CallMgrSpecific.Length =
  816. sizeof(Q2931_CALLMGR_PARAMETERS) +
  817. ATMLANE_CALL_IE_SPACE;
  818. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  819. pCallMgrParameters->CallMgrSpecific.Parameters;
  820. }
  821. else
  822. {
  823. //
  824. // Distribute space and link up pointers amongst the various
  825. // structures for the LECS PVC.
  826. //
  827. // pCallParameters------->+----------------------------+
  828. // | CO_CALL_PARAMETERS |
  829. // pCallMgrParameters---->+----------------------------+
  830. // | CO_CALL_MANAGER_PARAMETERS |
  831. // pMediaParameters------>+----------------------------+
  832. // | CO_MEDIA_PARAMETERS |
  833. // pAtmMediaParameters--->+----------------------------+
  834. // | ATM_MEDIA_PARAMETERS |
  835. // +----------------------------+
  836. //
  837. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  838. ((PUCHAR)pCallParameters +
  839. sizeof(CO_CALL_PARAMETERS));
  840. pCallParameters->CallMgrParameters = pCallMgrParameters;
  841. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  842. pCallMgrParameters->CallMgrSpecific.Length = 0;
  843. pMediaParameters = (PCO_MEDIA_PARAMETERS)
  844. pCallMgrParameters->CallMgrSpecific.Parameters;
  845. pCallParameters->MediaParameters = pMediaParameters;
  846. pAtmMediaParameters = (PATM_MEDIA_PARAMETERS)
  847. pMediaParameters->MediaSpecific.Parameters;
  848. }
  849. //
  850. // Call Manager generic flow paramters:
  851. //
  852. pCallMgrParameters->Transmit.TokenRate =
  853. pElan->pAdapter->LinkSpeed.Outbound/8*100; // cnvt decibits to bytes
  854. pCallMgrParameters->Transmit.PeakBandwidth =
  855. pElan->pAdapter->LinkSpeed.Outbound/8*100; // cnvt decibits to bytes
  856. pCallMgrParameters->Transmit.ServiceType = SERVICETYPE_BESTEFFORT;
  857. pCallMgrParameters->Receive.TokenRate =
  858. pElan->pAdapter->LinkSpeed.Inbound/8*100; // cnvt decibits to bytes
  859. pCallMgrParameters->Receive.PeakBandwidth =
  860. pElan->pAdapter->LinkSpeed.Inbound/8*100; // cnvt decibits to bytes
  861. pCallMgrParameters->Receive.ServiceType = SERVICETYPE_BESTEFFORT;
  862. if (ATM_ENTRY_TYPE_PEER == pAtmEntry->Type ||
  863. ATM_ENTRY_TYPE_BUS == pAtmEntry->Type)
  864. {
  865. //
  866. // Is data direct or multicast send VC so use configured size
  867. //
  868. pCallMgrParameters->Transmit.TokenBucketSize =
  869. pCallMgrParameters->Transmit.MaxSduSize =
  870. pCallMgrParameters->Receive.TokenBucketSize =
  871. pCallMgrParameters->Receive.MaxSduSize =
  872. pElan->MaxFrameSize;
  873. }
  874. else
  875. {
  876. //
  877. // Is control VC so use 1516 per spec
  878. //
  879. pCallMgrParameters->Transmit.TokenBucketSize =
  880. pCallMgrParameters->Transmit.MaxSduSize =
  881. pCallMgrParameters->Receive.TokenBucketSize =
  882. pCallMgrParameters->Receive.MaxSduSize =
  883. 1516;
  884. }
  885. if (!UsePvc)
  886. {
  887. //
  888. // SVC Q2931 Call Manager Parameters:
  889. //
  890. //
  891. // Called address:
  892. //
  893. NdisMoveMemory((PUCHAR)&(pAtmCallMgrParameters->CalledParty),
  894. (PUCHAR)&(pAtmEntry->AtmAddress),
  895. sizeof(ATM_ADDRESS));
  896. //
  897. // Calling address:
  898. //
  899. NdisMoveMemory((PUCHAR)&(pAtmCallMgrParameters->CallingParty),
  900. (PUCHAR)&(pElan->AtmAddress),
  901. sizeof(ATM_ADDRESS));
  902. //
  903. // LANE spec says that the following IEs MUST be present in the
  904. // SETUP message, so fill them all.
  905. //
  906. // AAL Parameters
  907. // Traffic Descriptor
  908. // Broadband Bearer Capability
  909. // Broadband Low Layer Info
  910. // QoS
  911. //
  912. //
  913. // Initialize the Info Element list
  914. //
  915. pAtmCallMgrParameters->InfoElementCount = 0;
  916. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  917. //
  918. // AAL Parameters:
  919. // AAL5
  920. // SDU size
  921. // 1516 for control
  922. // ELAN MaxFrameSize for data
  923. {
  924. UNALIGNED AAL5_PARAMETERS *pAal5;
  925. pIe->IEType = IE_AALParameters;
  926. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  927. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  928. pAalIe->AALType = AAL_TYPE_AAL5;
  929. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  930. if (ATM_ENTRY_TYPE_PEER == pAtmEntry->Type ||
  931. ATM_ENTRY_TYPE_BUS == pAtmEntry->Type)
  932. {
  933. //
  934. // Is data direct or multicast send VC so use configured size
  935. //
  936. pAal5->ForwardMaxCPCSSDUSize =
  937. pAal5->BackwardMaxCPCSSDUSize = (USHORT)pElan->MaxFrameSize;
  938. }
  939. else
  940. {
  941. //
  942. // Is control VC so use 1516 per spec
  943. //
  944. pAal5->ForwardMaxCPCSSDUSize =
  945. pAal5->BackwardMaxCPCSSDUSize = 1516;
  946. }
  947. }
  948. pAtmCallMgrParameters->InfoElementCount++;
  949. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  950. //
  951. // Traffic Descriptor:
  952. // Line Rate Best Effort
  953. //
  954. pIe->IEType = IE_TrafficDescriptor;
  955. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE;
  956. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)pIe->IE;
  957. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  958. LINKSPEED_TO_CPS(pElan->pAdapter->LinkSpeed.Outbound);
  959. DBGP((2, "MakeCall: fwd PeakCellRateCLP01 %d\n",
  960. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01));
  961. pTrafficDescriptor->BackwardTD.PeakCellRateCLP01 =
  962. LINKSPEED_TO_CPS(pElan->pAdapter->LinkSpeed.Inbound);
  963. DBGP((2, "MakeCall: bwd PeakCellRateCLP01 %d\n",
  964. pTrafficDescriptor->BackwardTD.PeakCellRateCLP01));
  965. pTrafficDescriptor->BestEffort = TRUE;
  966. pAtmCallMgrParameters->InfoElementCount++;
  967. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  968. //
  969. // Broadband Bearer Capability
  970. //
  971. pIe->IEType = IE_BroadbandBearerCapability;
  972. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE;
  973. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)pIe->IE;
  974. pBbc->BearerClass = BCOB_X;
  975. pBbc->TrafficType = TT_NOIND;
  976. pBbc->TimingRequirements = TR_NOIND;
  977. pBbc->ClippingSusceptability = CLIP_NOT;
  978. pBbc->UserPlaneConnectionConfig = UP_P2P;
  979. pAtmCallMgrParameters->InfoElementCount++;
  980. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  981. //
  982. // Broadband Lower Layer Information
  983. //
  984. pIe->IEType = IE_BLLI;
  985. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  986. pBlli = (PATM_BLLI_IE)pIe->IE;
  987. pBlli->Layer2Protocol = SAP_FIELD_ABSENT;
  988. pBlli->Layer3Protocol = BLLI_L3_ISO_TR9577;
  989. pBlli->Layer3IPI = BLLI_L3_IPI_SNAP;
  990. pBlli->SnapId[0] = 0x00;
  991. pBlli->SnapId[1] = 0xa0;
  992. pBlli->SnapId[2] = 0x3e;
  993. pBlli->SnapId[3] = 0x00;
  994. pBlli->SnapId[4] = 0x01; // default to Config Direct or
  995. // Control Direct
  996. if (ATM_ENTRY_TYPE_PEER == pAtmEntry->Type)
  997. {
  998. if (pElan->LanType == LANE_LANTYPE_ETH)
  999. {
  1000. pBlli->SnapId[4] = 0x02; // Eth/802.3 Data Direct
  1001. }
  1002. else
  1003. {
  1004. pBlli->SnapId[4] = 0x03; // 802.5 Data Direct
  1005. }
  1006. }
  1007. if (ATM_ENTRY_TYPE_BUS == pAtmEntry->Type)
  1008. {
  1009. if (pElan->LanType == LANE_LANTYPE_ETH)
  1010. {
  1011. pBlli->SnapId[4] = 0x04; // Eth/802.3 Multicast Send
  1012. }
  1013. else
  1014. {
  1015. pBlli->SnapId[4] = 0x05; // 802.5 Multicast Send
  1016. }
  1017. }
  1018. pAtmCallMgrParameters->InfoElementCount++;
  1019. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1020. //
  1021. // QoS
  1022. //
  1023. pIe->IEType = IE_QOSClass;
  1024. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE;
  1025. pQos = (PATM_QOS_CLASS_IE)pIe->IE;
  1026. pQos->QOSClassForward = pQos->QOSClassBackward = 0;
  1027. pAtmCallMgrParameters->InfoElementCount++;
  1028. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1029. }
  1030. else
  1031. {
  1032. //
  1033. // PVC Generic and ATM-specific Media Parameters
  1034. //
  1035. pMediaParameters->Flags = TRANSMIT_VC | RECEIVE_VC;
  1036. pMediaParameters->MediaSpecific.ParamType = ATM_MEDIA_SPECIFIC;
  1037. pMediaParameters->MediaSpecific.Length = sizeof(ATM_MEDIA_PARAMETERS);
  1038. pAtmMediaParameters->ConnectionId.Vpi = 0;
  1039. pAtmMediaParameters->ConnectionId.Vci = 17;
  1040. pAtmMediaParameters->AALType = AAL_TYPE_AAL5;
  1041. pAtmMediaParameters->Transmit.PeakCellRate =
  1042. LINKSPEED_TO_CPS(pElan->pAdapter->LinkSpeed.Outbound);
  1043. pAtmMediaParameters->Transmit.MaxSduSize = 1516;
  1044. pAtmMediaParameters->Transmit.ServiceCategory =
  1045. ATM_SERVICE_CATEGORY_UBR;
  1046. pAtmMediaParameters->Receive.PeakCellRate =
  1047. LINKSPEED_TO_CPS(pElan->pAdapter->LinkSpeed.Outbound);
  1048. pAtmMediaParameters->Receive.MaxSduSize = 1516;
  1049. pAtmMediaParameters->Receive.ServiceCategory =
  1050. ATM_SERVICE_CATEGORY_UBR;
  1051. //
  1052. // Set PVC flag here
  1053. //
  1054. pCallParameters->Flags |= PERMANENT_VC;
  1055. }
  1056. //
  1057. // We add the Call reference
  1058. // right here
  1059. //
  1060. AtmLaneReferenceVc(pVc, "call"); // Call reference (MakeCall coming up)
  1061. //
  1062. // We are ready to make the call. Before we do so, we need to
  1063. // link the VC structure to the ATM Entry, and release the
  1064. // ATM Entry lock
  1065. //
  1066. AtmLaneLinkVcToAtmEntry(pVc, pAtmEntry, FALSE);
  1067. RELEASE_ATM_ENTRY_LOCK(pAtmEntry); // acquired by caller
  1068. bIsLockHeld = FALSE;
  1069. //
  1070. // Make the Call now
  1071. //
  1072. Status = NdisClMakeCall(
  1073. NdisVcHandle,
  1074. pCallParameters,
  1075. (NDIS_HANDLE)NULL, // No Party context
  1076. (PNDIS_HANDLE)NULL // No Party handle expected
  1077. );
  1078. if (Status != NDIS_STATUS_PENDING)
  1079. {
  1080. AtmLaneMakeCallCompleteHandler(
  1081. Status,
  1082. ProtocolVcContext,
  1083. (NDIS_HANDLE)NULL, // No Party handle
  1084. pCallParameters
  1085. );
  1086. Status = NDIS_STATUS_PENDING;
  1087. }
  1088. //
  1089. // else the MakeCall complete handler will be called
  1090. // later
  1091. //
  1092. } while (FALSE);
  1093. if (bIsLockHeld)
  1094. {
  1095. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1096. }
  1097. DBGP((3, "MakeCall: pVc %x, returning status %x\n",
  1098. pVc, Status));
  1099. TRACEOUT(MakeCall);
  1100. return Status;
  1101. }
  1102. VOID
  1103. AtmLaneCloseCall(
  1104. IN PATMLANE_VC pVc LOCKIN NOLOCKOUT
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. Closes an existing call on a VC. It is assumed that a call exists
  1109. on the VC, and the VC is not linked with any ATM Entry.
  1110. NOTE: The caller is assumed to hold a lock to the VC structure,
  1111. and it will be released here.
  1112. SIDE EFFECT: If the NDIS call returns other than NDIS_STATUS_PENDING,
  1113. we call our CloseCall Complete handler from here.
  1114. Arguments:
  1115. pVc - Pointer to ATMLANE VC structure.
  1116. Return Value:
  1117. None
  1118. --*/
  1119. {
  1120. NDIS_HANDLE NdisVcHandle;
  1121. NDIS_HANDLE ProtocolVcContext;
  1122. NDIS_STATUS Status;
  1123. PATMLANE_ELAN pElan;
  1124. BOOLEAN WasRunning;
  1125. ULONG rc;
  1126. TRACEIN(CloseCall);
  1127. STRUCT_ASSERT(pVc, atmlane_vc);
  1128. NdisVcHandle = pVc->NdisVcHandle;
  1129. ProtocolVcContext = (NDIS_HANDLE)pVc;
  1130. pElan = pVc->pElan;
  1131. DBGP((1, "%d Closing call %x\n", pVc->pElan->ElanNumber, pVc));
  1132. rc = pVc->RefCount;
  1133. //
  1134. // Stop any timers running on this VC.
  1135. //
  1136. WasRunning = AtmLaneStopTimer(&(pVc->ReadyTimer), pElan);
  1137. if (WasRunning)
  1138. {
  1139. rc = AtmLaneDereferenceVc(pVc, "ready timer");
  1140. }
  1141. if (rc > 0)
  1142. {
  1143. WasRunning = AtmLaneStopTimer(&(pVc->AgingTimer), pElan);
  1144. if (WasRunning)
  1145. {
  1146. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  1147. }
  1148. }
  1149. //
  1150. // Continue only if the VC remains.
  1151. //
  1152. if (rc > 0)
  1153. {
  1154. //
  1155. // Check the call state on this VC. If the call is active,
  1156. // close it. Otherwise, simply mark the VC as closing, we'll
  1157. // continue this process when the current operation on the VC
  1158. // completes.
  1159. if (IS_FLAG_SET(pVc->Flags,
  1160. VC_CALL_STATE_MASK,
  1161. VC_CALL_STATE_ACTIVE) &&
  1162. (pVc->OutstandingSends == 0))
  1163. {
  1164. //
  1165. // Set VC call state to "Close Call in progress"
  1166. //
  1167. SET_FLAG(
  1168. pVc->Flags,
  1169. VC_CALL_STATE_MASK,
  1170. VC_CALL_STATE_CLOSE_IN_PROGRESS);
  1171. RELEASE_VC_LOCK(pVc);
  1172. DBGP((3,
  1173. "Closecall: NdisClCloseCall on NdisVcHandle %x\n",
  1174. NdisVcHandle));
  1175. Status = NdisClCloseCall(
  1176. NdisVcHandle,
  1177. (NDIS_HANDLE)NULL, // No Party Handle
  1178. (PVOID)NULL, // No Buffer
  1179. (UINT)0 // Size of above
  1180. );
  1181. if (Status != NDIS_STATUS_PENDING)
  1182. {
  1183. AtmLaneCloseCallCompleteHandler(
  1184. Status,
  1185. ProtocolVcContext,
  1186. (NDIS_HANDLE)NULL
  1187. );
  1188. }
  1189. }
  1190. else
  1191. {
  1192. //
  1193. // Some operation is going on here (call setup). Mark this
  1194. // VC so that we know what to do when this operation completes.
  1195. //
  1196. SET_FLAG(
  1197. pVc->Flags,
  1198. VC_CLOSE_STATE_MASK,
  1199. VC_CLOSE_STATE_CLOSING);
  1200. RELEASE_VC_LOCK(pVc);
  1201. }
  1202. }
  1203. //
  1204. // else the VC is gone.
  1205. //
  1206. TRACEOUT(CloseCall);
  1207. return;
  1208. }
  1209. NDIS_STATUS
  1210. AtmLaneCreateVcHandler(
  1211. IN NDIS_HANDLE ProtocolAfContext,
  1212. IN NDIS_HANDLE NdisVcHandle,
  1213. OUT PNDIS_HANDLE pProtocolVcContext
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. Entry point called by NDIS when the Call Manager wants to create
  1218. a new endpoint (VC). We allocate a new ATMLANE VC structure, and
  1219. return a pointer to it as our VC context.
  1220. Arguments:
  1221. ProtocolAfContext - Actually a pointer to the ATMLANE Interface structure
  1222. NdisVcHandle - Handle for this VC for all future references
  1223. pProtocolVcContext - Place where we (protocol) return our context for the VC
  1224. Return Value:
  1225. NDIS_STATUS_SUCCESS if we could create a VC
  1226. NDIS_STATUS_RESOURCES otherwise
  1227. --*/
  1228. {
  1229. PATMLANE_ELAN pElan;
  1230. PATMLANE_VC pVc;
  1231. NDIS_STATUS Status;
  1232. #if DEBUG_IRQL
  1233. KIRQL EntryIrql;
  1234. #endif
  1235. GET_ENTRY_IRQL(EntryIrql);
  1236. TRACEIN(CreateVcHandler);
  1237. pElan = (PATMLANE_ELAN)ProtocolAfContext;
  1238. pVc = AtmLaneAllocateVc(pElan);
  1239. if (pVc != NULL_PATMLANE_VC)
  1240. {
  1241. *pProtocolVcContext = (NDIS_HANDLE)pVc;
  1242. pVc->NdisVcHandle = NdisVcHandle;
  1243. pVc->Flags = VC_OWNER_IS_CALLMGR;
  1244. AtmLaneReferenceVc(pVc, "vc"); // Create VC ref
  1245. Status = NDIS_STATUS_SUCCESS;
  1246. }
  1247. else
  1248. {
  1249. Status = NDIS_STATUS_RESOURCES;
  1250. }
  1251. DBGP((3, "CreateVcHandler: pVc %x, Status %x\n", pVc, Status));
  1252. TRACEOUT(CreateVcHandler);
  1253. CHECK_EXIT_IRQL(EntryIrql);
  1254. return (Status);
  1255. }
  1256. NDIS_STATUS
  1257. AtmLaneDeleteVcHandler(
  1258. IN NDIS_HANDLE ProtocolVcContext
  1259. )
  1260. /*++
  1261. Routine Description:
  1262. Our Delete VC handler. This VC would have been allocated as a result
  1263. of a previous entry into our CreateVcHandler, and possibly used for
  1264. an incoming call.
  1265. At this time, this VC structure should be free of any calls, and we
  1266. simply free this.
  1267. Arguments:
  1268. ProtocolVcContext - pointer to our VC structure
  1269. Return Value:
  1270. NDIS_STATUS_SUCCESS always
  1271. --*/
  1272. {
  1273. PATMLANE_VC pVc;
  1274. ULONG rc; // Ref count on the VC
  1275. #if DEBUG_IRQL
  1276. KIRQL EntryIrql;
  1277. #endif
  1278. GET_ENTRY_IRQL(EntryIrql);
  1279. TRACEIN(DeleteVcHandler);
  1280. pVc = (PATMLANE_VC)ProtocolVcContext;
  1281. STRUCT_ASSERT(pVc, atmlane_vc);
  1282. ASSERT((pVc->Flags & VC_OWNER_MASK) == VC_OWNER_IS_CALLMGR);
  1283. ACQUIRE_VC_LOCK(pVc);
  1284. rc = AtmLaneDereferenceVc(pVc, "vc");
  1285. if (rc > 0)
  1286. {
  1287. //
  1288. // This can happen if there is a timer still running
  1289. // on this VC. When the timer elapses, the VC will be
  1290. // freed.
  1291. //
  1292. DBGP((2, "Delete VC handler: pVc %x, Flags %x, refcount %d\n",
  1293. pVc, pVc->Flags, rc));
  1294. RELEASE_VC_LOCK(pVc);
  1295. }
  1296. //
  1297. // else the VC is gone.
  1298. //
  1299. DBGP((3, "Delete Vc Handler: %x: done\n", pVc));
  1300. TRACEOUT(DeleteVcHandler);
  1301. CHECK_EXIT_IRQL(EntryIrql);
  1302. return (NDIS_STATUS_SUCCESS);
  1303. }
  1304. NDIS_STATUS
  1305. AtmLaneIncomingCallHandler(
  1306. IN NDIS_HANDLE ProtocolSapContext,
  1307. IN NDIS_HANDLE ProtocolVcContext,
  1308. IN OUT PCO_CALL_PARAMETERS pCallParameters
  1309. )
  1310. /*++
  1311. Routine Description:
  1312. This handler is called when there is an incoming call matching our
  1313. SAPs.
  1314. Arguments:
  1315. ProtocolSapContext - Pointer to ATMLANE Interface structure
  1316. ProtocolVcContext - Pointer to ATMLANE VC structure
  1317. pCallParameters - Call parameters
  1318. Return Value:
  1319. NDIS_STATUS_SUCCESS if we accept this call
  1320. NDIS_STATUS_FAILURE if we reject it.
  1321. --*/
  1322. {
  1323. PATMLANE_VC pVc;
  1324. PATMLANE_ATM_ENTRY pAtmEntry;
  1325. PATMLANE_ELAN pElan;
  1326. PATMLANE_SAP pSap;
  1327. Q2931_CALLMGR_PARAMETERS UNALIGNED * pAtmCallMgrParameters;
  1328. //
  1329. // To traverse the list of Info Elements
  1330. //
  1331. Q2931_IE UNALIGNED * pIe;
  1332. ULONG InfoElementCount;
  1333. //
  1334. // Info Elements in the incoming call, that are of interest to us.
  1335. // Initialize these to <not present>.
  1336. //
  1337. ATM_ADDRESS UNALIGNED * pCallingAddress = NULL;
  1338. AAL_PARAMETERS_IE UNALIGNED * pAal = NULL;
  1339. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor = NULL;
  1340. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc = NULL;
  1341. ATM_BLLI_IE UNALIGNED * pBlli = NULL;
  1342. ATM_QOS_CLASS_IE UNALIGNED * pQos = NULL;
  1343. AAL5_PARAMETERS UNALIGNED * pAal5;
  1344. UCHAR AddrTypeLen;
  1345. UCHAR SubaddrTypeLen;
  1346. PUCHAR pAtmSubaddress;
  1347. NDIS_STATUS Status;
  1348. ULONG Type;
  1349. ULONG rc;
  1350. #if DEBUG_IRQL
  1351. KIRQL EntryIrql;
  1352. #endif
  1353. GET_ENTRY_IRQL(EntryIrql);
  1354. TRACEIN(IncomingCallHandler);
  1355. pVc = (PATMLANE_VC)ProtocolVcContext;
  1356. pSap = (PATMLANE_SAP)ProtocolSapContext;
  1357. STRUCT_ASSERT(pVc, atmlane_vc);
  1358. STRUCT_ASSERT(pSap, atmlane_sap);
  1359. ASSERT((pVc->Flags & VC_TYPE_MASK) == VC_TYPE_UNUSED);
  1360. ASSERT((pVc->Flags & VC_OWNER_MASK) == VC_OWNER_IS_CALLMGR);
  1361. ASSERT((pVc->Flags & VC_CALL_STATE_MASK) == VC_CALL_STATE_IDLE);
  1362. pElan = pVc->pElan;
  1363. DBGP((3, "Incoming Call: pElan %x, pVc %x, pCallParams %x Type %s\n",
  1364. pElan, pVc, pCallParameters,
  1365. (pSap->LaneType == VC_LANE_TYPE_CONTROL_DISTRIBUTE?"LES":
  1366. (pSap->LaneType == VC_LANE_TYPE_MULTI_FORWARD?"BUS":"DATA"))
  1367. ));
  1368. do
  1369. {
  1370. //
  1371. // Start off with accepting the call
  1372. //
  1373. Status = NDIS_STATUS_SUCCESS;
  1374. //
  1375. // If Elan is going down or staying down then reject the call
  1376. //
  1377. if (ELAN_STATE_OPERATIONAL != pElan->AdminState)
  1378. {
  1379. DBGP((2, "IncomingCallHandler: Elan is down, rejecting call\n"));
  1380. Status = NDIS_STATUS_FAILURE;
  1381. break;
  1382. }
  1383. //
  1384. // Reject PVCs for now...
  1385. //
  1386. if ((pCallParameters->Flags & PERMANENT_VC) != 0)
  1387. {
  1388. DBGP((0, "IncomingCallHandler: PVCs not supported\n"));
  1389. Status = NDIS_STATUS_FAILURE;
  1390. break;
  1391. }
  1392. //
  1393. // Get the following info from the Incoming call:
  1394. // Calling Address
  1395. // AAL Parameters
  1396. // Traffic Descriptor
  1397. // Broadband Bearer Capability
  1398. // QoS
  1399. //
  1400. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  1401. pCallParameters->CallMgrParameters->CallMgrSpecific.Parameters;
  1402. pCallingAddress = &(pAtmCallMgrParameters->CallingParty);
  1403. InfoElementCount = pAtmCallMgrParameters->InfoElementCount;
  1404. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  1405. while (InfoElementCount--)
  1406. {
  1407. switch (pIe->IEType)
  1408. {
  1409. case IE_AALParameters:
  1410. pAal = (PAAL_PARAMETERS_IE)(pIe->IE);
  1411. break;
  1412. case IE_TrafficDescriptor:
  1413. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)(pIe->IE);
  1414. break;
  1415. case IE_BroadbandBearerCapability:
  1416. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)(pIe->IE);
  1417. break;
  1418. case IE_QOSClass:
  1419. pQos = (PATM_QOS_CLASS_IE)(pIe->IE);
  1420. break;
  1421. case IE_BLLI:
  1422. pBlli = (PATM_BLLI_IE)(pIe->IE);
  1423. break;
  1424. default:
  1425. break;
  1426. }
  1427. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  1428. }
  1429. //
  1430. // Make sure all mandatory IEs are present. If not, reject the call
  1431. //
  1432. if ((pAal == (PAAL_PARAMETERS_IE)NULL) ||
  1433. (pTrafficDescriptor == (PATM_TRAFFIC_DESCRIPTOR_IE)NULL) ||
  1434. (pBbc == (PATM_BROADBAND_BEARER_CAPABILITY_IE)NULL) ||
  1435. (pQos == (PATM_QOS_CLASS_IE)NULL) ||
  1436. (pBlli == (PATM_BLLI_IE)NULL))
  1437. {
  1438. DBGP((0, "IncomingCallHandler: IE missing: "
  1439. " AAL %x TRAF %x BBC %x QOS %x BLLI %x",
  1440. pAal,
  1441. pTrafficDescriptor,
  1442. pBbc,
  1443. pQos,
  1444. pBlli));
  1445. Status = NDIS_STATUS_FAILURE;
  1446. break;
  1447. }
  1448. //
  1449. // Calling Address must be present
  1450. //
  1451. if (((pCallParameters->Flags & PERMANENT_VC) == 0) &&
  1452. (pCallingAddress->NumberOfDigits == 0))
  1453. {
  1454. DBGP((0, "IncomingCallHandler: calling address missing\n"));
  1455. Status = NDIS_STATUS_INVALID_ADDRESS;
  1456. break;
  1457. }
  1458. //
  1459. // Make sure that the requested SDU sizes are sane.
  1460. // Originally this failed the call but now just a warning in DBG mode.
  1461. //
  1462. #if DBG
  1463. pAal5 = &(pAal->AALSpecificParameters.AAL5Parameters);
  1464. switch (pSap->LaneType)
  1465. {
  1466. case VC_LANE_TYPE_CONTROL_DISTRIBUTE: // LES incoming
  1467. if (pAal5->ForwardMaxCPCSSDUSize != 1516)
  1468. {
  1469. DBGP((0, "IncomingCallHandler: (Warning) ForwardMaxCPCSSDUSize %d"
  1470. "Incorrect for Control Distribute VCC\n",
  1471. pAal5->ForwardMaxCPCSSDUSize));
  1472. }
  1473. break;
  1474. case VC_LANE_TYPE_MULTI_FORWARD: // BUS incoming
  1475. if (pAal5->ForwardMaxCPCSSDUSize != pElan->MaxFrameSize)
  1476. {
  1477. DBGP((0, "IncomingCallHandler: (Warning) ForwardMaxCPCSSDUSize %d "
  1478. "Invalid for Multicast Forward VCC\n",
  1479. pAal5->ForwardMaxCPCSSDUSize));
  1480. }
  1481. break;
  1482. case VC_LANE_TYPE_DATA_DIRECT: // PEER
  1483. if (pAal5->ForwardMaxCPCSSDUSize != pElan->MaxFrameSize)
  1484. {
  1485. DBGP((0, "IncomingCallHandler: (Warning) ForwardMaxCPCSSDUSize %d "
  1486. "Invalid for Data Direct VCC\n",
  1487. pAal5->ForwardMaxCPCSSDUSize));
  1488. }
  1489. if (pAal5->BackwardMaxCPCSSDUSize != pElan->MaxFrameSize)
  1490. {
  1491. DBGP((0, "IncomingCallHandler: (Warning) BackwardMaxCPCSSDUSize %d "
  1492. "Invalid for Data Direct VCC\n",
  1493. pAal5->BackwardMaxCPCSSDUSize));
  1494. }
  1495. break;
  1496. }
  1497. #endif
  1498. //
  1499. // Earlier SAP matching problem required looking at the
  1500. // BLLI. It was corrected. Now it is just redundant.
  1501. //
  1502. switch (pBlli->SnapId[4])
  1503. {
  1504. case 0x01:
  1505. Type = VC_LANE_TYPE_CONTROL_DISTRIBUTE;
  1506. break;
  1507. case 0x02:
  1508. Type = VC_LANE_TYPE_DATA_DIRECT;
  1509. if (pElan->LanType == LANE_LANTYPE_TR)
  1510. {
  1511. DBGP((0, "IncomingCallHandler: Got ETH call on TR LAN\n"));
  1512. Status = NDIS_STATUS_FAILURE;
  1513. }
  1514. break;
  1515. case 0x03:
  1516. Type = VC_LANE_TYPE_DATA_DIRECT;
  1517. if (pElan->LanType == LANE_LANTYPE_ETH)
  1518. {
  1519. DBGP((0, "IncomingCallHandler: Got TR call on ETH LAN\n"));
  1520. Status = NDIS_STATUS_FAILURE;
  1521. }
  1522. break;
  1523. case 0x04:
  1524. Type = VC_LANE_TYPE_MULTI_FORWARD;
  1525. if (pElan->LanType == LANE_LANTYPE_TR)
  1526. {
  1527. DBGP((0, "IncomingCallHandler: Got ETH call on TR LAN\n"));
  1528. Status = NDIS_STATUS_FAILURE;
  1529. }
  1530. break;
  1531. case 0x05:
  1532. Type = VC_LANE_TYPE_MULTI_FORWARD;
  1533. if (pElan->LanType == LANE_LANTYPE_ETH)
  1534. {
  1535. DBGP((0, "IncomingCallHandler: Got TR call on ETH LAN\n"));
  1536. Status = NDIS_STATUS_FAILURE;
  1537. }
  1538. break;
  1539. }
  1540. if (NDIS_STATUS_SUCCESS != Status)
  1541. {
  1542. break;
  1543. }
  1544. if (Type != pSap->LaneType)
  1545. {
  1546. DBGP((0,
  1547. "IncomingCallHandler: Type %d from BLLI"
  1548. " differs from Type %d in SAP\n",
  1549. Type, pSap->LaneType));
  1550. }
  1551. //
  1552. // Now link up the VC to ATM Entry based on type
  1553. //
  1554. pVc->LaneType = Type;
  1555. switch (Type)
  1556. {
  1557. case VC_LANE_TYPE_CONTROL_DISTRIBUTE: // LES incoming
  1558. DBGP((1, "%d Incoming call %x from LES\n", pVc->pElan->ElanNumber, pVc));
  1559. pAtmEntry = pElan->pLesAtmEntry;
  1560. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  1561. {
  1562. Status = NDIS_STATUS_FAILURE;
  1563. break;
  1564. }
  1565. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1566. ACQUIRE_VC_LOCK_DPC(pVc);
  1567. NdisMoveMemory( // copy in caller's addr
  1568. &pVc->CallingAtmAddress,
  1569. pCallingAddress,
  1570. sizeof(ATM_ADDRESS)
  1571. );
  1572. if (pAtmEntry->pVcIncoming != NULL_PATMLANE_VC)
  1573. {
  1574. DBGP((0, "IncomingCallHandler: Redundant LES incoming call\n"));
  1575. Status = NDIS_STATUS_FAILURE;
  1576. }
  1577. else
  1578. {
  1579. AtmLaneLinkVcToAtmEntry(pVc, pAtmEntry, TRUE);
  1580. SET_FLAG(
  1581. pAtmEntry->Flags,
  1582. ATM_ENTRY_STATE_MASK,
  1583. ATM_ENTRY_CONNECTED
  1584. );
  1585. pVc->Flags |= (VC_TYPE_SVC|VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1586. }
  1587. RELEASE_VC_LOCK_DPC(pVc);
  1588. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1589. break;
  1590. case VC_LANE_TYPE_MULTI_FORWARD: // BUS incoming
  1591. DBGP((1, "%d Incoming call %x from BUS\n", pVc->pElan->ElanNumber, pVc));
  1592. pAtmEntry = pElan->pBusAtmEntry;
  1593. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  1594. {
  1595. Status = NDIS_STATUS_FAILURE;
  1596. break;
  1597. }
  1598. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1599. ACQUIRE_VC_LOCK_DPC(pVc);
  1600. NdisMoveMemory( // copy in caller's addr
  1601. &pVc->CallingAtmAddress,
  1602. pCallingAddress,
  1603. sizeof(ATM_ADDRESS)
  1604. );
  1605. if (pAtmEntry->pVcIncoming != NULL_PATMLANE_VC)
  1606. {
  1607. DBGP((0, "IncomingCallHandler: Redundant BUS incoming call\n"));
  1608. Status = NDIS_STATUS_FAILURE;
  1609. }
  1610. else
  1611. {
  1612. AtmLaneLinkVcToAtmEntry(pVc, pAtmEntry, TRUE);
  1613. SET_FLAG(
  1614. pAtmEntry->Flags,
  1615. ATM_ENTRY_STATE_MASK,
  1616. ATM_ENTRY_CONNECTED
  1617. );
  1618. pVc->Flags |= (VC_TYPE_SVC|VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1619. }
  1620. RELEASE_VC_LOCK_DPC(pVc);
  1621. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1622. break;
  1623. case VC_LANE_TYPE_DATA_DIRECT: // PEER
  1624. DBGP((1, "%d Incoming call %x from PEER\n", pVc->pElan->ElanNumber, pVc));
  1625. //
  1626. // Find/create an ATM Entry
  1627. //
  1628. pAtmEntry = AtmLaneSearchForAtmAddress(
  1629. pElan,
  1630. pCallingAddress->Address,
  1631. ATM_ENTRY_TYPE_PEER,
  1632. TRUE
  1633. );
  1634. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  1635. {
  1636. Status = NDIS_STATUS_RESOURCES;
  1637. break;
  1638. }
  1639. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1640. //
  1641. // Remember caller's address
  1642. //
  1643. ACQUIRE_VC_LOCK_DPC(pVc);
  1644. NdisMoveMemory(
  1645. &pVc->CallingAtmAddress,
  1646. pCallingAddress,
  1647. sizeof(ATM_ADDRESS)
  1648. );
  1649. //
  1650. // Start with with normal timeout,
  1651. // AtmLaneLinkVcToAtmEntry will accelerate if necessary.
  1652. //
  1653. pVc->AgingTime = pElan->VccTimeout;
  1654. //
  1655. // Link up the VC with ATM Entry
  1656. //
  1657. if (pAtmEntry->pVcList != NULL_PATMLANE_VC)
  1658. {
  1659. DBGP((2,
  1660. "IncomingCallHandler: Multiple VCs for Dest ATM Addr\n"));
  1661. }
  1662. AtmLaneLinkVcToAtmEntry(pVc, pAtmEntry, FALSE);
  1663. SET_FLAG(
  1664. pAtmEntry->Flags,
  1665. ATM_ENTRY_STATE_MASK,
  1666. ATM_ENTRY_CONNECTED
  1667. );
  1668. pVc->Flags |= (VC_TYPE_SVC|VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1669. RELEASE_VC_LOCK_DPC(pVc);
  1670. //
  1671. // Remove ref added by SearchFor...
  1672. //
  1673. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "search");
  1674. if (rc != 0)
  1675. {
  1676. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1677. }
  1678. break;
  1679. }
  1680. break;
  1681. }
  1682. while (FALSE);
  1683. DBGP((3, "Incoming call: pVc %x, Status %x\n", pVc, Status));
  1684. TRACEOUT(IncomingCallHandler);
  1685. CHECK_EXIT_IRQL(EntryIrql);
  1686. return Status;
  1687. }
  1688. VOID
  1689. AtmLaneCallConnectedHandler(
  1690. IN NDIS_HANDLE ProtocolVcContext
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. This handler is called as the final step in an incoming call, to inform
  1695. us that the call is fully setup.
  1696. For a PVC, we link the ATMLANE VC structure in the list of unresolved PVCs,
  1697. and use InATMLANE to resolve both the IP and ATM addresses of the other
  1698. end.
  1699. For an SVC,
  1700. Arguments:
  1701. ProtocolVcContext - Pointer to ATMLANE VC structure
  1702. Return Value:
  1703. None
  1704. --*/
  1705. {
  1706. PATMLANE_VC pVc;
  1707. PATMLANE_ELAN pElan;
  1708. #if DEBUG_IRQL
  1709. KIRQL EntryIrql;
  1710. #endif
  1711. GET_ENTRY_IRQL(EntryIrql);
  1712. TRACEIN(CallConnectedHandler);
  1713. pVc = (PATMLANE_VC)ProtocolVcContext;
  1714. STRUCT_ASSERT(pVc, atmlane_vc);
  1715. ASSERT((pVc->Flags & VC_CALL_STATE_MASK)
  1716. == VC_CALL_STATE_INCOMING_IN_PROGRESS);
  1717. ACQUIRE_VC_LOCK(pVc);
  1718. DBGP((1, "%d Incoming call %x connected\n", pVc->pElan->ElanNumber, pVc));
  1719. //
  1720. // Note down that a call is active on this VC.
  1721. //
  1722. SET_FLAG(
  1723. pVc->Flags,
  1724. VC_CALL_STATE_MASK,
  1725. VC_CALL_STATE_ACTIVE
  1726. );
  1727. AtmLaneReferenceVc(pVc, "call"); // Incoming call reference
  1728. DBGP((2, "CallConnectedHandler: pVc %x Flags %x pAtmEntry %x\n",
  1729. pVc, pVc->Flags, pVc->pAtmEntry));
  1730. pElan = pVc->pElan;
  1731. STRUCT_ASSERT(pElan, atmlane_elan);
  1732. if (ELAN_STATE_OPERATIONAL == pElan->AdminState)
  1733. {
  1734. if (pVc->LaneType == VC_LANE_TYPE_DATA_DIRECT)
  1735. {
  1736. //
  1737. // Start ready protocol on non-server connections
  1738. // only if ready indication not already received.
  1739. //
  1740. if (!IS_FLAG_SET(
  1741. pVc->Flags,
  1742. VC_READY_STATE_MASK,
  1743. VC_READY_INDICATED))
  1744. {
  1745. DBGP((2, "CallConnectedHandler: pVc %x Starting Ready Timer\n", pVc));
  1746. SET_FLAG(
  1747. pVc->Flags,
  1748. VC_READY_STATE_MASK,
  1749. VC_READY_WAIT
  1750. );
  1751. pVc->RetriesLeft = 1;
  1752. AtmLaneReferenceVc(pVc, "ready timer");
  1753. AtmLaneStartTimer(
  1754. pElan,
  1755. &pVc->ReadyTimer,
  1756. AtmLaneReadyTimeout,
  1757. pElan->ConnComplTimer,
  1758. pVc);
  1759. }
  1760. //
  1761. // Start VC aging timer
  1762. //
  1763. AtmLaneReferenceVc(pVc, "aging timer");
  1764. AtmLaneStartTimer(
  1765. pElan,
  1766. &pVc->AgingTimer,
  1767. AtmLaneVcAgingTimeout,
  1768. pVc->AgingTime,
  1769. (PVOID)pVc
  1770. );
  1771. }
  1772. else
  1773. {
  1774. SET_FLAG(
  1775. pVc->Flags,
  1776. VC_READY_STATE_MASK,
  1777. VC_READY_INDICATED
  1778. );
  1779. }
  1780. RELEASE_VC_LOCK(pVc);
  1781. }
  1782. else
  1783. {
  1784. //
  1785. // The elan is going down. Close this call.
  1786. //
  1787. AtmLaneCloseCall(pVc);
  1788. //
  1789. // VC lock released in above
  1790. //
  1791. }
  1792. TRACEOUT(CallConnectedHandler);
  1793. CHECK_EXIT_IRQL(EntryIrql);
  1794. return;
  1795. }
  1796. VOID
  1797. AtmLaneIncomingCloseHandler(
  1798. IN NDIS_STATUS CloseStatus,
  1799. IN NDIS_HANDLE ProtocolVcContext,
  1800. IN PVOID pCloseData OPTIONAL,
  1801. IN UINT Size OPTIONAL
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. This handler is called when a call is closed, either by the network
  1806. or by the remote peer.
  1807. Arguments:
  1808. CloseStatus - Reason for the call clearing
  1809. ProtocolVcContext - Actually a pointer to the ATMLANE VC structure
  1810. pCloseData - Additional info about the close
  1811. Size - Length of above
  1812. Return Value:
  1813. None
  1814. --*/
  1815. {
  1816. PATMLANE_VC pVc;
  1817. PATMLANE_ATM_ENTRY pAtmEntry;
  1818. PATMLANE_ELAN pElan;
  1819. ULONG rc; // Ref Count
  1820. BOOLEAN IsServer = FALSE;
  1821. ULONG ServerType = 0;
  1822. #if DEBUG_IRQL
  1823. KIRQL EntryIrql;
  1824. #endif
  1825. GET_ENTRY_IRQL(EntryIrql);
  1826. TRACEIN(IncomingCloseHandler);
  1827. pVc = (PATMLANE_VC)ProtocolVcContext;
  1828. STRUCT_ASSERT(pVc, atmlane_vc);
  1829. ACQUIRE_VC_LOCK(pVc);
  1830. pVc->Flags |= VC_SEEN_INCOMING_CLOSE;
  1831. pAtmEntry = pVc->pAtmEntry;
  1832. pElan = pVc->pElan;
  1833. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  1834. {
  1835. //
  1836. // Determine if this is server connection
  1837. //
  1838. IsServer = (ATM_ENTRY_TYPE_PEER == pAtmEntry->Type) ? FALSE : TRUE;
  1839. if (IsServer)
  1840. {
  1841. ServerType = pAtmEntry->Type;
  1842. }
  1843. //
  1844. // Unlink the VC from the AtmEntry
  1845. //
  1846. if (AtmLaneUnlinkVcFromAtmEntry(pVc))
  1847. {
  1848. rc = AtmLaneDereferenceVc(pVc, "atm");
  1849. ASSERT(rc > 0);
  1850. }
  1851. }
  1852. //
  1853. // If we're seeing this just after accepting an incomingcall,
  1854. // fake the call state to Active, so that AtmLaneCloseCall will
  1855. // tear down the call.
  1856. //
  1857. if (IS_FLAG_SET(pVc->Flags,
  1858. VC_CALL_STATE_MASK,
  1859. VC_CALL_STATE_INCOMING_IN_PROGRESS))
  1860. {
  1861. SET_FLAG(
  1862. pVc->Flags,
  1863. VC_CALL_STATE_MASK,
  1864. VC_CALL_STATE_ACTIVE);
  1865. AtmLaneReferenceVc(pVc, "call"); // Incoming call reference - CloseCall
  1866. }
  1867. //
  1868. // Complete tearing down the call
  1869. //
  1870. AtmLaneCloseCall(pVc);
  1871. //
  1872. // If server connection - notify the event handler
  1873. //
  1874. if (IsServer)
  1875. {
  1876. ACQUIRE_ELAN_LOCK(pElan);
  1877. switch(ServerType)
  1878. {
  1879. case ATM_ENTRY_TYPE_LECS:
  1880. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_LECS_CALL_CLOSED, 0);
  1881. break;
  1882. case ATM_ENTRY_TYPE_LES:
  1883. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_LES_CALL_CLOSED, 0);
  1884. break;
  1885. case ATM_ENTRY_TYPE_BUS:
  1886. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_BUS_CALL_CLOSED, 0);
  1887. break;
  1888. }
  1889. RELEASE_ELAN_LOCK(pElan);
  1890. }
  1891. TRACEOUT(IncomingCloseHandler);
  1892. CHECK_EXIT_IRQL(EntryIrql);
  1893. return;
  1894. }
  1895. VOID
  1896. AtmLaneIncomingDropPartyHandler(
  1897. IN NDIS_STATUS DropStatus,
  1898. IN NDIS_HANDLE ProtocolPartyContext,
  1899. IN PVOID pCloseData OPTIONAL,
  1900. IN UINT Size OPTIONAL
  1901. )
  1902. /*++
  1903. Routine Description:
  1904. This handler is called if the network (or remote peer) drops
  1905. a leaf node from a point-to-multipoint call rooted at us.
  1906. Since we don't use point-to-multipoint calls, we should never
  1907. see one of these.
  1908. Arguments:
  1909. Not relevant to us since we never expect to see this.
  1910. Return Value:
  1911. None
  1912. --*/
  1913. {
  1914. TRACEIN(IncomingDropPartyHandler);
  1915. DBGP((0, "IncomingDropPartyHandler: UNEXPECTED CALL!\n"));
  1916. ASSERT(FALSE);
  1917. TRACEOUT(IncomingDropPartyHandler);
  1918. return;
  1919. }
  1920. VOID
  1921. AtmLaneQosChangeHandler(
  1922. IN NDIS_HANDLE ProtocolVcContext,
  1923. IN PCO_CALL_PARAMETERS pCallParameters
  1924. )
  1925. /*++
  1926. Routine Description:
  1927. This handler is called if the remote peer modifies call parameters
  1928. "on the fly", i.e. after the call is established and running.
  1929. This isn't supported by existing ATM signalling, and shouldn't happen,
  1930. but we'll allow this.
  1931. FUTURE: The FlowSpecs associated with the call are affected by this.
  1932. Arguments:
  1933. ProtocolVcContext - Pointer to our ATMLANE VC structure
  1934. pCallParameters - updated call parameters.
  1935. Return Value:
  1936. None
  1937. --*/
  1938. {
  1939. PATMLANE_VC pVc;
  1940. TRACEIN(QosChangeHandler);
  1941. pVc = (PATMLANE_VC)ProtocolVcContext;
  1942. DBGP((0, "Ignoring Qos Change, VC: %x\n", pVc));
  1943. TRACEOUT(QosChangeHandler);
  1944. return;
  1945. }
  1946. VOID
  1947. AtmLaneRegisterSapCompleteHandler(
  1948. IN NDIS_STATUS Status,
  1949. IN NDIS_HANDLE ProtocolSapContext,
  1950. IN PCO_SAP pSap,
  1951. IN NDIS_HANDLE NdisSapHandle
  1952. )
  1953. /*++
  1954. Routine Description:
  1955. This routine is called to indicate completion of a call to
  1956. NdisClRegisterSap. If the call was successful, save the
  1957. allocated NdisSapHandle in our SAP structure.
  1958. Arguments:
  1959. Status - Status of Register SAP
  1960. ProtocolSapContext - Pointer to our ATMLANE Interface structure
  1961. pSap - SAP information we'd passed in the call
  1962. NdisSapHandle - SAP Handle
  1963. Return Value:
  1964. None
  1965. --*/
  1966. {
  1967. PATMLANE_SAP pAtmLaneSap;
  1968. #if DEBUG_IRQL
  1969. KIRQL EntryIrql;
  1970. #endif
  1971. GET_ENTRY_IRQL(EntryIrql);
  1972. TRACEIN(RegisterSapCompleteHandler);
  1973. pAtmLaneSap = (PATMLANE_SAP)ProtocolSapContext;
  1974. if (Status == NDIS_STATUS_SUCCESS)
  1975. {
  1976. pAtmLaneSap->NdisSapHandle = NdisSapHandle;
  1977. SET_FLAG(pAtmLaneSap->Flags,
  1978. SAP_REG_STATE_MASK,
  1979. SAP_REG_STATE_REGISTERED);
  1980. NdisInterlockedIncrement(&pAtmLaneSap->pElan->SapsRegistered);
  1981. if (pAtmLaneSap->pElan->SapsRegistered == 3)
  1982. AtmLaneQueueElanEvent(
  1983. pAtmLaneSap->pElan,
  1984. ELAN_EVENT_SAPS_REGISTERED,
  1985. Status);
  1986. }
  1987. else
  1988. {
  1989. SET_FLAG(pAtmLaneSap->Flags,
  1990. SAP_REG_STATE_MASK,
  1991. SAP_REG_STATE_IDLE);
  1992. AtmLaneQueueElanEvent(
  1993. pAtmLaneSap->pElan,
  1994. ELAN_EVENT_SAPS_REGISTERED,
  1995. Status);
  1996. }
  1997. TRACEOUT(RegisterSapCompleteHandler);
  1998. CHECK_EXIT_IRQL(EntryIrql);
  1999. return;
  2000. }
  2001. VOID
  2002. AtmLaneDeregisterSapCompleteHandler(
  2003. IN NDIS_STATUS Status,
  2004. IN NDIS_HANDLE ProtocolSapContext
  2005. )
  2006. /*++
  2007. Routine Description:
  2008. This routine is called when a previous call to NdisClDeregisterSap
  2009. has completed. If it was successful, we update the state of the ATMLANE
  2010. SAP structure representing the Sap.
  2011. Arguments:
  2012. Status - Status of the Deregister SAP request
  2013. ProtocolSapContext - Pointer to our ATMLANE SAP structure
  2014. Return Value:
  2015. None
  2016. --*/
  2017. {
  2018. PATMLANE_ELAN pElan;
  2019. PATMLANE_SAP pAtmLaneSap;
  2020. #if DEBUG_IRQL
  2021. KIRQL EntryIrql;
  2022. #endif
  2023. GET_ENTRY_IRQL(EntryIrql);
  2024. TRACEIN(DeregisterSapCompleteHandler);
  2025. if (Status == NDIS_STATUS_SUCCESS)
  2026. {
  2027. pAtmLaneSap = (PATMLANE_SAP)ProtocolSapContext;
  2028. STRUCT_ASSERT(pAtmLaneSap, atmlane_sap);
  2029. pElan = pAtmLaneSap->pElan;
  2030. ACQUIRE_ELAN_LOCK(pElan);
  2031. pAtmLaneSap->NdisSapHandle = NULL;
  2032. SET_FLAG(pAtmLaneSap->Flags,
  2033. SAP_REG_STATE_MASK,
  2034. SAP_REG_STATE_IDLE);
  2035. RELEASE_ELAN_LOCK(pElan);
  2036. }
  2037. TRACEOUT(DeregisterSapCompleteHandler);
  2038. CHECK_EXIT_IRQL(EntryIrql);
  2039. return;
  2040. }
  2041. VOID
  2042. AtmLaneMakeCallCompleteHandler(
  2043. IN NDIS_STATUS Status,
  2044. IN NDIS_HANDLE ProtocolVcContext,
  2045. IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
  2046. IN PCO_CALL_PARAMETERS pCallParameters
  2047. )
  2048. /*++
  2049. Routine Description:
  2050. This routine is called when an outgoing call request (NdisClMakeCall)
  2051. has completed. The "Status" parameter indicates whether the call was
  2052. successful or not.
  2053. If the call was successful and this is a server connection then
  2054. the an event handler is called. If it is a peer connection then
  2055. ???
  2056. If the call failed ??
  2057. Arguments:
  2058. Status - Result of the NdisClMakeCall
  2059. ProtocolVcContext - Pointer to ATMLANE VC structure
  2060. NdisPartyHandle - Not used (no point-to-multipoint calls)
  2061. pCallParameters - Pointer to call parameters
  2062. Return Value:
  2063. None
  2064. --*/
  2065. {
  2066. PATMLANE_VC pVc;
  2067. PATMLANE_ATM_ENTRY pAtmEntry;
  2068. PATMLANE_MAC_ENTRY pMacEntry;
  2069. PATMLANE_MAC_ENTRY PMacEntryNext;
  2070. PATMLANE_ELAN pElan;
  2071. ULONG rc;
  2072. NDIS_HANDLE NdisVcHandle;
  2073. BOOLEAN IsServer;
  2074. ULONG EventStatus;
  2075. #if DEBUG_IRQL
  2076. KIRQL EntryIrql;
  2077. #endif
  2078. GET_ENTRY_IRQL(EntryIrql);
  2079. TRACEIN(MakeCallCompleteHandler);
  2080. //
  2081. // Initialize
  2082. //
  2083. pVc = (PATMLANE_VC)ProtocolVcContext;
  2084. STRUCT_ASSERT(pVc, atmlane_vc);
  2085. ACQUIRE_VC_LOCK(pVc);
  2086. DBGP((3, "MakeCallCompleteHandler: Status %x, pVc %x, pAtmEntry %x\n",
  2087. Status, pVc, pVc->pAtmEntry));
  2088. pElan = pVc->pElan;
  2089. DBGP((1, "%d Outgoing call %x %s\n", pVc->pElan->ElanNumber, pVc,
  2090. (Status == NDIS_STATUS_SUCCESS)?"complete":"failed"));
  2091. if ((ELAN_STATE_OPERATIONAL == pElan->AdminState) &&
  2092. (!IS_FLAG_SET(pVc->Flags,
  2093. VC_CLOSE_STATE_MASK,
  2094. VC_CLOSE_STATE_CLOSING)))
  2095. {
  2096. pAtmEntry = pVc->pAtmEntry;
  2097. STRUCT_ASSERT(pAtmEntry, atmlane_atm);
  2098. //
  2099. // Determine if this is server connection
  2100. //
  2101. IsServer = (ATM_ENTRY_TYPE_PEER == pAtmEntry->Type) ? FALSE : TRUE;
  2102. if (Status == NDIS_STATUS_SUCCESS)
  2103. {
  2104. //
  2105. // Update the call state on this VC.
  2106. //
  2107. SET_FLAG(pVc->Flags,
  2108. VC_CALL_STATE_MASK,
  2109. VC_CALL_STATE_ACTIVE);
  2110. //
  2111. // Update the call type on this VC.
  2112. //
  2113. if (pCallParameters->Flags & PERMANENT_VC)
  2114. {
  2115. SET_FLAG(pVc->Flags,
  2116. VC_TYPE_MASK,
  2117. VC_TYPE_PVC);
  2118. }
  2119. else
  2120. {
  2121. SET_FLAG(pVc->Flags,
  2122. VC_TYPE_MASK,
  2123. VC_TYPE_SVC);
  2124. }
  2125. //
  2126. // Start VC aging timer if not server
  2127. //
  2128. if (!IsServer)
  2129. {
  2130. AtmLaneReferenceVc(pVc, "aging timer");
  2131. AtmLaneStartTimer(
  2132. pElan,
  2133. &pVc->AgingTimer,
  2134. AtmLaneVcAgingTimeout,
  2135. pVc->AgingTime,
  2136. (PVOID)pVc
  2137. );
  2138. }
  2139. //
  2140. // Update the ready state on this VC
  2141. //
  2142. SET_FLAG(pVc->Flags,
  2143. VC_READY_STATE_MASK,
  2144. VC_READY_INDICATED);
  2145. if (!IsServer)
  2146. {
  2147. AtmLaneSendReadyIndication(pElan, pVc);
  2148. //
  2149. // VC lock released in above
  2150. //
  2151. }
  2152. else
  2153. {
  2154. RELEASE_VC_LOCK(pVc);
  2155. }
  2156. //
  2157. // Update the Atm Entry
  2158. //
  2159. // Clear call-in-progress and mark connected
  2160. //
  2161. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2162. pAtmEntry->Flags &= ~ ATM_ENTRY_CALLINPROGRESS;
  2163. SET_FLAG(
  2164. pAtmEntry->Flags,
  2165. ATM_ENTRY_STATE_MASK,
  2166. ATM_ENTRY_CONNECTED);
  2167. //
  2168. // Go through the Mac Entry List and see if any
  2169. // need the flush protocol initiated.
  2170. //
  2171. pMacEntry = pAtmEntry->pMacEntryList;
  2172. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2173. while (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2174. {
  2175. PATMLANE_MAC_ENTRY pNextMacEntry;
  2176. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2177. pNextMacEntry = pMacEntry->pNextToAtm;
  2178. if (IS_FLAG_SET(
  2179. pMacEntry->Flags,
  2180. MAC_ENTRY_STATE_MASK,
  2181. MAC_ENTRY_RESOLVED))
  2182. {
  2183. //
  2184. // Start the Flush protocol
  2185. //
  2186. pMacEntry->RetriesLeft = 0;
  2187. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2188. AtmLaneStartTimer(
  2189. pElan,
  2190. &pMacEntry->FlushTimer,
  2191. AtmLaneFlushTimeout,
  2192. pElan->FlushTimeout,
  2193. (PVOID)pMacEntry
  2194. );
  2195. SET_FLAG(
  2196. pMacEntry->Flags,
  2197. MAC_ENTRY_STATE_MASK,
  2198. MAC_ENTRY_FLUSHING);
  2199. //
  2200. // Send the flush
  2201. //
  2202. AtmLaneSendFlushRequest(pElan, pMacEntry, pAtmEntry);
  2203. //
  2204. // MacEntry lock released in above
  2205. //
  2206. }
  2207. else
  2208. {
  2209. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2210. }
  2211. pMacEntry = pNextMacEntry;
  2212. }
  2213. }
  2214. else
  2215. {
  2216. //
  2217. // The call failed.
  2218. //
  2219. SET_FLAG(pVc->Flags,
  2220. VC_CALL_STATE_MASK,
  2221. VC_CALL_STATE_IDLE);
  2222. //
  2223. // Clear call in progress on Atm Entry
  2224. // Add temp reference to keep the AtmEntry around
  2225. //
  2226. RELEASE_VC_LOCK(pVc);
  2227. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2228. pAtmEntry->Flags &= ~ATM_ENTRY_CALLINPROGRESS;
  2229. AtmLaneReferenceAtmEntry(pAtmEntry, "temp1");
  2230. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2231. ACQUIRE_VC_LOCK(pVc);
  2232. //
  2233. // Delete the Call reference
  2234. //
  2235. rc = AtmLaneDereferenceVc(pVc, "call");
  2236. ASSERT(rc > 0);
  2237. //
  2238. // Unlink this VC from the ATM Entry it belonged to.
  2239. //
  2240. ASSERT(pVc->pAtmEntry != NULL_PATMLANE_ATM_ENTRY);
  2241. if (AtmLaneUnlinkVcFromAtmEntry(pVc))
  2242. {
  2243. rc = AtmLaneDereferenceVc(pVc, "atm");
  2244. ASSERT(rc > 0);
  2245. }
  2246. //
  2247. // Delete the CreateVc reference
  2248. //
  2249. NdisVcHandle = pVc->NdisVcHandle;
  2250. rc = AtmLaneDereferenceVc(pVc, "vc"); // Create Vc ref
  2251. if (rc > 0)
  2252. {
  2253. RELEASE_VC_LOCK(pVc);
  2254. }
  2255. //
  2256. // Delete the NDIS association
  2257. //
  2258. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2259. DBGP((3,
  2260. "MakeCallCompleteHandler: DeleteVc Vc %x NdisVcHandle %x\n",
  2261. pVc, NdisVcHandle));
  2262. //
  2263. // Abort all the MAC entries attached to this Atm Entry.
  2264. //
  2265. pMacEntry = pAtmEntry->pMacEntryList;
  2266. while ( pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2267. {
  2268. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2269. AtmLaneAbortMacEntry(pMacEntry);
  2270. ASSERT(pAtmEntry->pMacEntryList != pMacEntry);
  2271. pMacEntry = pAtmEntry->pMacEntryList;
  2272. }
  2273. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2274. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "temp1");
  2275. if (rc > 0)
  2276. {
  2277. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2278. }
  2279. }
  2280. //
  2281. // Free the Call Parameters allocated in MakeCall().
  2282. //
  2283. FREE_MEM(pCallParameters);
  2284. //
  2285. // If this is server connection then
  2286. // send an event to the elan state machine.
  2287. //
  2288. if (IsServer)
  2289. {
  2290. ACQUIRE_ELAN_LOCK(pElan);
  2291. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_SVR_CALL_COMPLETE, Status);
  2292. RELEASE_ELAN_LOCK(pElan);
  2293. }
  2294. }
  2295. else
  2296. {
  2297. //
  2298. // The Elan is going down and/or we are aborting the
  2299. // ATM entry: clean up everything first.
  2300. //
  2301. //
  2302. // Free the Call Parameters allocated in MakeCall().
  2303. //
  2304. FREE_MEM(pCallParameters);
  2305. //
  2306. // Unlink this VC from the ATM Entry
  2307. //
  2308. if (pVc->pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2309. {
  2310. if (AtmLaneUnlinkVcFromAtmEntry(pVc))
  2311. {
  2312. rc = AtmLaneDereferenceVc(pVc, "atm");
  2313. ASSERT(rc > 0);
  2314. }
  2315. }
  2316. if (NDIS_STATUS_SUCCESS == Status)
  2317. {
  2318. //
  2319. // The call had been set up successfully, so close it.
  2320. //
  2321. //
  2322. // Update the call state on this VC.
  2323. //
  2324. SET_FLAG(pVc->Flags,
  2325. VC_CALL_STATE_MASK,
  2326. VC_CALL_STATE_ACTIVE);
  2327. AtmLaneCloseCall(pVc);
  2328. //
  2329. // The VC lock is released by CloseCall
  2330. //
  2331. }
  2332. else
  2333. {
  2334. // MakeCall had failed. (And the ELAN is going down)
  2335. SET_FLAG(pVc->Flags,
  2336. VC_CALL_STATE_MASK,
  2337. VC_CALL_STATE_IDLE);
  2338. //
  2339. // Delete the CreateVc reference
  2340. //
  2341. NdisVcHandle = pVc->NdisVcHandle;
  2342. rc = AtmLaneDereferenceVc(pVc, "vc"); // Create Vc ref
  2343. if (rc > 0)
  2344. {
  2345. RELEASE_VC_LOCK(pVc);
  2346. }
  2347. //
  2348. // Delete the NDIS association
  2349. //
  2350. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2351. DBGP((3,
  2352. "MakeCallCompleteHandler: Deleted NDIS VC on pVc %x: NdisVcHandle %x\n",
  2353. pVc, NdisVcHandle));
  2354. }
  2355. }
  2356. TRACEOUT(MakeCallCompleteHandler);
  2357. CHECK_EXIT_IRQL(EntryIrql);
  2358. return;
  2359. }
  2360. VOID
  2361. AtmLaneCloseCallCompleteHandler(
  2362. IN NDIS_STATUS Status,
  2363. IN NDIS_HANDLE ProtocolVcContext,
  2364. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
  2365. )
  2366. /*++
  2367. Routine Description:
  2368. This routine handles completion of a previous NdisClCloseCall.
  2369. It is assumed that Status is always NDIS_STATUS_SUCCESS.
  2370. Arguments:
  2371. Status - Status of the Close Call.
  2372. ProtocolVcContext - Pointer to ATMLANE VC structure.
  2373. ProtocolPartyContext - Not used.
  2374. Return Value:
  2375. None
  2376. --*/
  2377. {
  2378. PATMLANE_VC pVc;
  2379. ULONG rc; // Ref Count
  2380. NDIS_HANDLE NdisVcHandle;
  2381. #if DEBUG_IRQL
  2382. KIRQL EntryIrql;
  2383. #endif
  2384. GET_ENTRY_IRQL(EntryIrql);
  2385. TRACEIN(CloseCallCompleteHandler);
  2386. pVc = (PATMLANE_VC)ProtocolVcContext;
  2387. STRUCT_ASSERT(pVc, atmlane_vc);
  2388. DBGP((1, "%d Close call %x complete\n", pVc->pElan->ElanNumber, pVc));
  2389. ACQUIRE_VC_LOCK(pVc);
  2390. rc = AtmLaneDereferenceVc(pVc, "call"); // Call reference
  2391. SET_FLAG(pVc->Flags,
  2392. VC_CALL_STATE_MASK,
  2393. VC_CALL_STATE_IDLE);
  2394. //
  2395. // If this VC belongs to us, delete it.
  2396. //
  2397. if (IS_FLAG_SET(pVc->Flags,
  2398. VC_OWNER_MASK,
  2399. VC_OWNER_IS_ATMLANE))
  2400. {
  2401. NdisVcHandle = pVc->NdisVcHandle;
  2402. rc = AtmLaneDereferenceVc(pVc, "vc"); // Create Vc ref
  2403. if (rc > 0)
  2404. {
  2405. RELEASE_VC_LOCK(pVc);
  2406. }
  2407. //
  2408. // Delete the NDIS association
  2409. //
  2410. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2411. DBGP((3, "CloseCallComplete: deleted NDIS VC on pVc %x: NdisVcHandle %x\n",
  2412. pVc, NdisVcHandle));
  2413. }
  2414. else
  2415. {
  2416. //
  2417. // VC belongs to the Call Manager -- take it back to the
  2418. // state it was when it was just created (via our CreateVcHandler).
  2419. // The Call Manager can either re-use it or delete it.
  2420. //
  2421. pVc->Flags = VC_OWNER_IS_CALLMGR;
  2422. RELEASE_VC_LOCK(pVc);
  2423. }
  2424. TRACEOUT(CloseCallCompleteHandler);
  2425. CHECK_EXIT_IRQL(EntryIrql);
  2426. return;
  2427. }
  2428. VOID
  2429. AtmLaneAddPartyCompleteHandler(
  2430. IN NDIS_STATUS Status,
  2431. IN NDIS_HANDLE ProtocolPartyContext,
  2432. IN NDIS_HANDLE NdisPartyHandle,
  2433. IN PCO_CALL_PARAMETERS pCallParameters
  2434. )
  2435. /*++
  2436. Routine Description:
  2437. This routine is called on completion of a previous call to
  2438. NdisClAddParty. Since we don't use point-to-multipoint connections,
  2439. this should never get called.
  2440. Arguments:
  2441. <Don't care>
  2442. Return Value:
  2443. None
  2444. --*/
  2445. {
  2446. TRACEIN(AddPartyCompleteHandler);
  2447. DBGP((0, "Add Party Complete unexpectedly called\n"));
  2448. TRACEOUT(AddPartyCompleteHandler);
  2449. return;
  2450. }
  2451. VOID
  2452. AtmLaneDropPartyCompleteHandler(
  2453. IN NDIS_STATUS Status,
  2454. IN NDIS_HANDLE ProtocolPartyContext
  2455. )
  2456. /*++
  2457. Routine Description:
  2458. This routine is called on completion of a previous call to
  2459. NdisClDropParty. Since we don't use point-to-multipoint connections,
  2460. this should never get called.
  2461. Arguments:
  2462. <Don't care>
  2463. Return Value:
  2464. None
  2465. --*/
  2466. {
  2467. TRACEIN(DropPartyCompleteHandler);
  2468. DBGP((0, "Drop Party Complete unexpectedly called\n"));
  2469. TRACEOUT(DropPartyCompleteHandler);
  2470. return;
  2471. }
  2472. VOID
  2473. AtmLaneModifyQosCompleteHandler(
  2474. IN NDIS_STATUS Status,
  2475. IN NDIS_HANDLE ProtocolVcContext,
  2476. IN PCO_CALL_PARAMETERS pCallParameters
  2477. )
  2478. /*++
  2479. Routine Description:
  2480. This routine is called on completion of a previous call to
  2481. NdisClModifyCallQoS. Since we don't call this, this should never
  2482. get called.
  2483. Arguments:
  2484. <Don't care>
  2485. Return Value:
  2486. None
  2487. --*/
  2488. {
  2489. TRACEIN(ModifyQosCompleteHandler);
  2490. DBGP((0, "Modify QOS Complete unexpectedly called\n"));
  2491. TRACEOUT(ModifyQosCompleteHandler);
  2492. return;
  2493. }
  2494. NDIS_STATUS
  2495. AtmLaneSendNdisCoRequest(
  2496. IN NDIS_HANDLE NdisAdapterHandle,
  2497. IN NDIS_HANDLE NdisAfHandle,
  2498. IN PNDIS_REQUEST pNdisRequest,
  2499. IN NDIS_REQUEST_TYPE RequestType,
  2500. IN NDIS_OID Oid,
  2501. IN PVOID pBuffer,
  2502. IN ULONG BufferLength
  2503. )
  2504. /*++
  2505. Routine Description:
  2506. Send an NDIS Connection Oriented request to the Call Manager. We
  2507. allocate an NDIS_REQUEST structure, link the supplied buffer to it,
  2508. and send the request. If the request does not pend, we call our
  2509. completion routine from here.
  2510. Arguments:
  2511. NdisAdapterHandle - Binding Handle to be used in the request
  2512. NdisAfHandle - AF Handle value to be used in the request
  2513. pNdisRequest - Pointer to NDIS request structure
  2514. RequestType - Set/Query information
  2515. Oid - OID to be passed in the request
  2516. pBuffer - place for value(s)
  2517. BufferLength - length of above
  2518. Return Value:
  2519. Status of the NdisCoRequest.
  2520. --*/
  2521. {
  2522. NDIS_STATUS Status;
  2523. TRACEIN(SendNdisCoRequest);
  2524. //
  2525. // Fill in the NDIS Request structure
  2526. //
  2527. pNdisRequest->RequestType = RequestType;
  2528. if (RequestType == NdisRequestQueryInformation)
  2529. {
  2530. pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  2531. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
  2532. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
  2533. pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
  2534. pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
  2535. }
  2536. else
  2537. {
  2538. pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
  2539. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
  2540. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
  2541. pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  2542. pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  2543. }
  2544. if (NULL == NdisAfHandle ||
  2545. NULL == NdisAdapterHandle)
  2546. {
  2547. Status = NDIS_STATUS_INTERFACE_DOWN;
  2548. }
  2549. else
  2550. {
  2551. Status = NdisCoRequest(
  2552. NdisAdapterHandle,
  2553. NdisAfHandle,
  2554. NULL, // No VC handle
  2555. NULL, // No Party Handle
  2556. pNdisRequest);
  2557. }
  2558. TRACEOUT(SendNdisCoRequest);
  2559. return (Status);
  2560. }
  2561. NDIS_STATUS
  2562. AtmLaneCoRequestHandler(
  2563. IN NDIS_HANDLE ProtocolAfContext,
  2564. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  2565. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  2566. IN OUT PNDIS_REQUEST pNdisRequest
  2567. )
  2568. /*++
  2569. Routine Description:
  2570. This routine is called by NDIS when our Call Manager sends us an
  2571. NDIS Request. NDIS Requests that are of significance to us are:
  2572. - OID_CO_ADDRESS_CHANGE
  2573. The set of addresses registered with the switch has changed,
  2574. i.e. address registration is complete. We issue an NDIS Request
  2575. ourselves to get the list of addresses registered.
  2576. - OID_CO_SIGNALING_ENABLED
  2577. We ignore this as of now.
  2578. - OID_CO_SIGNALING_DISABLED
  2579. We ignore this for now.
  2580. - OID_CO_AF_CLOSE
  2581. The Call manager wants us to shut down this AF open (== ELAN).
  2582. We ignore all other OIDs.
  2583. Arguments:
  2584. ProtocolAfContext - Our context for the Address Family binding,
  2585. which is a pointer to the ATMLANE Interface.
  2586. ProtocolVcContext - Our context for a VC, which is a pointer to
  2587. an ATMLANE VC structure.
  2588. ProtocolPartyContext - Our context for a Party. Since we don't do
  2589. PMP, this is ignored (must be NULL).
  2590. pNdisRequest - Pointer to the NDIS Request.
  2591. Return Value:
  2592. NDIS_STATUS_SUCCESS if we recognized the OID
  2593. NDIS_STATUS_NOT_RECOGNIZED if we didn't.
  2594. --*/
  2595. {
  2596. PATMLANE_ELAN pElan;
  2597. PATMLANE_ADAPTER pAdapter;
  2598. NDIS_STATUS Status;
  2599. #if DEBUG_IRQL
  2600. KIRQL EntryIrql;
  2601. #endif
  2602. GET_ENTRY_IRQL(EntryIrql);
  2603. TRACEIN(CoRequestHandler);
  2604. pElan = (PATMLANE_ELAN)ProtocolAfContext;
  2605. STRUCT_ASSERT(pElan, atmlane_elan);
  2606. //
  2607. // Initialize
  2608. //
  2609. Status = NDIS_STATUS_NOT_RECOGNIZED;
  2610. if (pNdisRequest->RequestType == NdisRequestSetInformation)
  2611. {
  2612. switch (pNdisRequest->DATA.SET_INFORMATION.Oid)
  2613. {
  2614. case OID_CO_ADDRESS_CHANGE:
  2615. DBGP((1, "CoRequestHandler: CO_ADDRESS_CHANGE\n"));
  2616. //
  2617. // The Call Manager says that the list of addresses
  2618. // registered on this interface has changed. Get the
  2619. // (potentially) new ATM address for this interface.
  2620. //
  2621. ACQUIRE_ELAN_LOCK(pElan);
  2622. pElan->AtmInterfaceUp = FALSE;
  2623. //
  2624. // zero out the Elan's ATM address
  2625. //
  2626. NdisZeroMemory((PUCHAR)&(pElan->AtmAddress), sizeof(ATM_ADDRESS));
  2627. RELEASE_ELAN_LOCK(pElan);
  2628. AtmLaneGetAtmAddress(pElan);
  2629. Status = NDIS_STATUS_SUCCESS;
  2630. break;
  2631. case OID_CO_SIGNALING_ENABLED:
  2632. DBGP((1, "CoRequestHandler: CO_SIGNALING_ENABLED\n"));
  2633. // ignored for now
  2634. Status = NDIS_STATUS_SUCCESS;
  2635. break;
  2636. case OID_CO_SIGNALING_DISABLED:
  2637. DBGP((1, "CoRequestHandler: CO_SIGNALING_DISABLED\n"));
  2638. // Ignored for now
  2639. Status = NDIS_STATUS_SUCCESS;
  2640. break;
  2641. case OID_CO_AF_CLOSE:
  2642. DBGP((0, "CoRequestHandler: CO_AF_CLOSE on ELAN %x/%x\n", pElan, pElan->Flags));
  2643. pAdapter = pElan->pAdapter;
  2644. ACQUIRE_ADAPTER_LOCK(pAdapter);
  2645. while (pAdapter->Flags & ADAPTER_FLAGS_BOOTSTRAP_IN_PROGRESS)
  2646. {
  2647. RELEASE_ADAPTER_LOCK(pAdapter);
  2648. (VOID)WAIT_ON_BLOCK_STRUCT(&pAdapter->UnbindBlock);
  2649. ACQUIRE_ADAPTER_LOCK(pAdapter);
  2650. }
  2651. RELEASE_ADAPTER_LOCK(pAdapter);
  2652. ACQUIRE_ELAN_LOCK(pElan);
  2653. pElan->Flags |= ELAN_SAW_AF_CLOSE;
  2654. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_STOP, 0, 1*1000);
  2655. RELEASE_ELAN_LOCK(pElan);
  2656. Status = NDIS_STATUS_SUCCESS;
  2657. break;
  2658. default:
  2659. break;
  2660. }
  2661. }
  2662. TRACEOUT(CoRequestHandler);
  2663. CHECK_EXIT_IRQL(EntryIrql);
  2664. return (Status);
  2665. }
  2666. VOID
  2667. AtmLaneCoRequestCompleteHandler(
  2668. IN NDIS_STATUS Status,
  2669. IN NDIS_HANDLE ProtocolAfContext,
  2670. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  2671. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  2672. IN PNDIS_REQUEST pNdisRequest
  2673. )
  2674. /*++
  2675. Routine Description:
  2676. This routine is called by NDIS when a previous call to NdisCoRequest
  2677. that had pended, is complete. We handle this based on the request
  2678. we had sent, which has to be one of:
  2679. - OID_CO_GET_ADDRESSES
  2680. Get all addresses registered on the specified AF binding.
  2681. Arguments:
  2682. Status - Status of the Request.
  2683. ProtocolAfContext - Our context for the Address Family binding,
  2684. which is a pointer to the ATMLANE Interface.
  2685. ProtocolVcContext - Our context for a VC, which is a pointer to
  2686. an ATMLANE VC structure.
  2687. ProtocolPartyContext - Our context for a Party. Since we don't do
  2688. PMP, this is ignored (must be NULL).
  2689. pNdisRequest - Pointer to the NDIS Request.
  2690. Return Value:
  2691. None
  2692. --*/
  2693. {
  2694. PATMLANE_ELAN pElan;
  2695. ULONG Oid;
  2696. #if DEBUG_IRQL
  2697. KIRQL EntryIrql;
  2698. #endif
  2699. GET_ENTRY_IRQL(EntryIrql);
  2700. TRACEIN(CoRequestCompleteHandler);
  2701. pElan = (PATMLANE_ELAN)ProtocolAfContext;
  2702. STRUCT_ASSERT(pElan, atmlane_elan);
  2703. if (pNdisRequest->RequestType == NdisRequestQueryInformation)
  2704. {
  2705. switch (pNdisRequest->DATA.QUERY_INFORMATION.Oid)
  2706. {
  2707. case OID_CO_GET_ADDRESSES:
  2708. AtmLaneGetAtmAddressComplete(
  2709. Status,
  2710. pElan,
  2711. pNdisRequest
  2712. );
  2713. break;
  2714. case OID_ATM_LECS_ADDRESS:
  2715. AtmLaneGetLecsIlmiComplete(
  2716. Status,
  2717. pElan,
  2718. pNdisRequest
  2719. );
  2720. break;
  2721. default:
  2722. DBGP((0, "CoRequestComplete: pNdisReq %x, unknown Query Oid %x\n",
  2723. pNdisRequest,
  2724. pNdisRequest->DATA.QUERY_INFORMATION.Oid));
  2725. ASSERT(FALSE);
  2726. break;
  2727. }
  2728. }
  2729. else
  2730. {
  2731. Oid = pNdisRequest->DATA.QUERY_INFORMATION.Oid;
  2732. switch (Oid)
  2733. {
  2734. case OID_ATM_MY_IP_NM_ADDRESS:
  2735. DBGP((3, "CoRequestComplete: IP addr: Status %x\n", Status));
  2736. break;
  2737. default:
  2738. DBGP((0, "CoRequestComplete: pNdisReq %x, unknown Set Oid %x\n",
  2739. pNdisRequest, Oid));
  2740. ASSERT(FALSE);
  2741. break;
  2742. }
  2743. }
  2744. FREE_MEM(pNdisRequest);
  2745. TRACEOUT(CoRequestCompleteHandler);
  2746. CHECK_EXIT_IRQL(EntryIrql);
  2747. return;
  2748. }
  2749. NDIS_STATUS
  2750. AtmLaneGetAtmAddress(
  2751. IN PATMLANE_ELAN pElan
  2752. )
  2753. /*++
  2754. Routine Description:
  2755. Send a request to the Call Manager to retrieve the ATM address
  2756. registered with the switch on the given interface.
  2757. This is called when the Call Manager tells us that there has been
  2758. a change in its list of addresses registered with the switch.
  2759. Normally, this happens when we start up our signalling stack (i.e.
  2760. initial address registration), but it might happen during runtime,
  2761. for example, if the link goes down and up, or we get physically
  2762. connected to a different switch...
  2763. In any case, we issue an NDIS Request to the Call Manager to retrieve
  2764. the first address it has registered. Action then continues in
  2765. AtmLaneGetAtmAddressComplete.
  2766. Arguments:
  2767. pElan - Elan structure for which this event occurred.
  2768. Return Value:
  2769. None
  2770. --*/
  2771. {
  2772. PNDIS_REQUEST pNdisRequest;
  2773. NDIS_HANDLE NdisAfHandle;
  2774. NDIS_HANDLE NdisAdapterHandle;
  2775. NDIS_STATUS Status;
  2776. PCO_ADDRESS_LIST pAddressList;
  2777. ULONG RequestSize;
  2778. TRACEIN(GetAtmAddress);
  2779. DBGP((3, "GetAtmAddress: pElan %x\n", pElan));
  2780. ACQUIRE_ELAN_LOCK(pElan);
  2781. NdisAfHandle = pElan->NdisAfHandle;
  2782. NdisAdapterHandle = pElan->NdisAdapterHandle;
  2783. RELEASE_ELAN_LOCK(pElan);
  2784. do
  2785. {
  2786. if (NULL == NdisAfHandle ||
  2787. NULL == NdisAdapterHandle)
  2788. {
  2789. DBGP((0, "%d Aborting GetAtmAddress, Elan %x, AfH %x AdH %x\n",
  2790. pElan->ElanNumber, pElan, NdisAfHandle, NdisAdapterHandle));
  2791. Status = NDIS_STATUS_FAILURE;
  2792. break;
  2793. }
  2794. //
  2795. // Allocate all that we need.
  2796. //
  2797. RequestSize = sizeof(NDIS_REQUEST) +
  2798. sizeof(CO_ADDRESS_LIST) +
  2799. sizeof(CO_ADDRESS) +
  2800. sizeof(ATM_ADDRESS);
  2801. ALLOC_MEM(&pNdisRequest, RequestSize);
  2802. if ((PNDIS_REQUEST)NULL == pNdisRequest)
  2803. {
  2804. Status = NDIS_STATUS_RESOURCES;
  2805. break;
  2806. }
  2807. //
  2808. // Init request data
  2809. //
  2810. pAddressList = (PCO_ADDRESS_LIST)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
  2811. NdisZeroMemory(pAddressList, sizeof(CO_ADDRESS_LIST));
  2812. //
  2813. // Send off request
  2814. //
  2815. Status = AtmLaneSendNdisCoRequest(
  2816. NdisAdapterHandle,
  2817. NdisAfHandle,
  2818. pNdisRequest,
  2819. NdisRequestQueryInformation,
  2820. OID_CO_GET_ADDRESSES,
  2821. (PVOID)pAddressList,
  2822. RequestSize - sizeof(NDIS_REQUEST)
  2823. );
  2824. if (NDIS_STATUS_PENDING != Status)
  2825. {
  2826. AtmLaneCoRequestCompleteHandler(
  2827. Status,
  2828. (NDIS_HANDLE)pElan, // ProtocolAfContext
  2829. NULL, // Vc Context
  2830. NULL, // Party Context
  2831. pNdisRequest
  2832. );
  2833. }
  2834. } while (FALSE);
  2835. TRACEOUT(GetAtmAddress);
  2836. return Status;
  2837. }
  2838. VOID
  2839. AtmLaneGetAtmAddressComplete(
  2840. IN NDIS_STATUS Status,
  2841. IN PATMLANE_ELAN pElan,
  2842. IN PNDIS_REQUEST pNdisRequest
  2843. )
  2844. /*++
  2845. Routine Description:
  2846. This is called when we have a reply to our previous call to
  2847. NdisCoRequest(OID_CO_GET_ADDRESSES). If any addresses returned,
  2848. copy the first for our address.
  2849. If the address is different from the previous signal an event.
  2850. Arguments:
  2851. Status - result of the request
  2852. pElan - ATMLANE Elan on which the request was issued
  2853. pNdisRequest - the request itself. This will also contain the
  2854. returned address.
  2855. Return Value:
  2856. None
  2857. --*/
  2858. {
  2859. PCO_ADDRESS_LIST pAddressList;
  2860. ATM_ADDRESS UNALIGNED * pAtmAddress;
  2861. TRACEIN(GetAtmAddressComplete);
  2862. DBGP((3, "GetAtmAddressComplete: pElan %x, Status %x\n",
  2863. pElan, Status));
  2864. if (NDIS_STATUS_SUCCESS == Status)
  2865. {
  2866. pAddressList = (PCO_ADDRESS_LIST)
  2867. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  2868. DBGP((3, "GetAtmAddressComplete: pElan %x, Count %d\n",
  2869. pElan, pAddressList->NumberOfAddresses));
  2870. if (pAddressList->NumberOfAddresses > 0)
  2871. {
  2872. //
  2873. // We have at least one address
  2874. //
  2875. ACQUIRE_ELAN_LOCK(pElan);
  2876. //
  2877. // Mark AtmInterface "up"
  2878. //
  2879. pElan->AtmInterfaceUp = TRUE;
  2880. pAtmAddress = (ATM_ADDRESS UNALIGNED *)(pAddressList->AddressList.Address);
  2881. //
  2882. // See if address(without selector byte) differs from
  2883. // one we already have. First time will differ as ATM
  2884. // address starts as all zeros.
  2885. //
  2886. if (!NdisEqualMemory(
  2887. pElan->AtmAddress.Address,
  2888. pAtmAddress->Address,
  2889. ATM_ADDRESS_LENGTH-1))
  2890. {
  2891. //
  2892. // Copy in the new address
  2893. //
  2894. NdisMoveMemory(
  2895. (PUCHAR)&(pElan->AtmAddress),
  2896. (PUCHAR)pAtmAddress,
  2897. sizeof(ATM_ADDRESS)
  2898. );
  2899. //
  2900. // Patch the selector byte with the Elan number.
  2901. //
  2902. pElan->AtmAddress.Address[ATM_ADDRESS_LENGTH-1] =
  2903. (UCHAR)(pElan->ElanNumber);
  2904. DBGP((1,
  2905. "%d GetAtmAddressComplete: New ATMAddr %s\n",
  2906. pElan->ElanNumber,
  2907. AtmAddrToString(pElan->AtmAddress.Address)
  2908. ));
  2909. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_NEW_ATM_ADDRESS, Status, 1*1000);
  2910. }
  2911. RELEASE_ELAN_LOCK(pElan);
  2912. }
  2913. }
  2914. //
  2915. // else our request failed! Wait for another ADDRESS_CHANGE notification
  2916. //
  2917. TRACEOUT(GetAtmAddressComplete);
  2918. return;
  2919. }
  2920. NDIS_STATUS
  2921. AtmLaneGetLecsIlmi(
  2922. IN PATMLANE_ELAN pElan LOCKIN NOLOCKOUT
  2923. )
  2924. /*++
  2925. Routine Description:
  2926. Send a request to the Call Manager to retrieve (using ILMI)
  2927. the ATM address of the LECS.
  2928. In any case, we issue an NDIS Request to the Call Manager to retrieve
  2929. the address. Action then continues in AtmLaneGetLecsIlmiComplete.
  2930. Arguments:
  2931. pElan - Elan structure for which this event occurred.
  2932. Return Value:
  2933. None
  2934. --*/
  2935. {
  2936. PNDIS_REQUEST pNdisRequest;
  2937. NDIS_HANDLE NdisAfHandle;
  2938. NDIS_HANDLE NdisAdapterHandle;
  2939. NDIS_STATUS Status;
  2940. PATM_ADDRESS pAtmAddress;
  2941. ULONG RequestSize;
  2942. TRACEIN(GetIlmiLecs);
  2943. DBGP((3, "GetIlmiLecs: pElan %x\n", pElan));
  2944. ACQUIRE_ELAN_LOCK(pElan);
  2945. NdisAfHandle = pElan->NdisAfHandle;
  2946. NdisAdapterHandle = pElan->NdisAdapterHandle;
  2947. RELEASE_ELAN_LOCK(pElan);
  2948. pNdisRequest = NULL;
  2949. //
  2950. // Zero LecsAddress in Elan
  2951. //
  2952. NdisZeroMemory(&pElan->LecsAddress, sizeof(ATM_ADDRESS));
  2953. do
  2954. {
  2955. //
  2956. // Allocate NDIS_REQUEST plus one ATM_ADDRESS
  2957. //
  2958. RequestSize = sizeof(NDIS_REQUEST) + sizeof(ATM_ADDRESS);
  2959. ALLOC_MEM(&pNdisRequest, RequestSize);
  2960. if ((PNDIS_REQUEST)NULL == pNdisRequest)
  2961. {
  2962. Status = NDIS_STATUS_RESOURCES;
  2963. break;
  2964. }
  2965. //
  2966. // Init request data
  2967. //
  2968. pAtmAddress = (PATM_ADDRESS)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
  2969. NdisZeroMemory(pAtmAddress, sizeof(ATM_ADDRESS));
  2970. //
  2971. // Send off request
  2972. //
  2973. Status = AtmLaneSendNdisCoRequest(
  2974. NdisAdapterHandle,
  2975. NdisAfHandle,
  2976. pNdisRequest,
  2977. NdisRequestQueryInformation,
  2978. OID_ATM_LECS_ADDRESS,
  2979. (PVOID)pAtmAddress,
  2980. RequestSize - sizeof(NDIS_REQUEST)
  2981. );
  2982. }
  2983. while (FALSE);
  2984. if ((NDIS_STATUS_PENDING != Status) &&
  2985. (pNdisRequest != NULL))
  2986. {
  2987. AtmLaneCoRequestCompleteHandler(
  2988. Status,
  2989. (NDIS_HANDLE)pElan, // ProtocolAfContext
  2990. NULL, // Vc Context
  2991. NULL, // Party Context
  2992. pNdisRequest
  2993. );
  2994. }
  2995. TRACEOUT(GetIlmiLecs);
  2996. return Status;
  2997. }
  2998. VOID
  2999. AtmLaneGetLecsIlmiComplete(
  3000. IN NDIS_STATUS Status,
  3001. IN PATMLANE_ELAN pElan,
  3002. IN PNDIS_REQUEST pNdisRequest
  3003. )
  3004. /*++
  3005. Routine Description:
  3006. This is called when we have a reply to our previous call to
  3007. NdisCoRequest(OID_CO_GET_ADDRESSES). Check if we got any addresses
  3008. back: if we did, store the address as our Local ATM Address, and
  3009. if conditions are ripe, start registering ourselves with the ARP
  3010. server.
  3011. Since we allocated the NDIS request, free it here.
  3012. Arguments:
  3013. Status - result of the request
  3014. pElan - ATMLANE Elan on which the request was issued
  3015. pNdisRequest - the request itself. This will also contain the
  3016. returned address.
  3017. Return Value:
  3018. None
  3019. --*/
  3020. {
  3021. PATM_ADDRESS UNALIGNED * pAtmAddress;
  3022. TRACEIN(GetLecsIlmiComplete);
  3023. ACQUIRE_ELAN_LOCK(pElan);
  3024. if (NDIS_STATUS_SUCCESS == Status)
  3025. {
  3026. pAtmAddress = (PATM_ADDRESS UNALIGNED *)
  3027. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  3028. //
  3029. // We have the address. Copy it to elan run-time variable.
  3030. //
  3031. NdisMoveMemory(
  3032. (PUCHAR)&(pElan->LecsAddress),
  3033. (PUCHAR)pAtmAddress,
  3034. sizeof(ATM_ADDRESS)
  3035. );
  3036. DBGP((1, "%d ILMI LECS Addr %s\n",
  3037. pElan->ElanNumber,
  3038. AtmAddrToString(pElan->LecsAddress.Address)
  3039. ));
  3040. }
  3041. else
  3042. {
  3043. DBGP((3, "%d OID_ATM_LECS_ADDRESS Failed %x\n",
  3044. pElan->ElanNumber,
  3045. Status));
  3046. }
  3047. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_GOT_ILMI_LECS_ADDR, Status);
  3048. RELEASE_ELAN_LOCK(pElan);
  3049. TRACEOUT(HandleGetIlmiLecsComplete);
  3050. return;
  3051. }