Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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