Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1571 lines
35 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This module contains several miscellaneous routines like, ReferenceVC
  7. dereferenceVC etc.
  8. Author:
  9. Anil Francis Thomas (10/98)
  10. Environment:
  11. Kernel
  12. Revision History:
  13. DChen 092499 Remove try/except block in VerifyRecvOpenContext
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #define MODULE_ID MODULE_MISC
  18. NDIS_STATUS AtmSmAllocVc(
  19. IN PATMSM_ADAPTER pAdapt,
  20. OUT PATMSM_VC *ppVc,
  21. IN ULONG VcType,
  22. IN NDIS_HANDLE NdisVcHandle
  23. )
  24. /*++
  25. Routine Description:
  26. This routine is used to create a VC structure and link to an adapter
  27. Arguments:
  28. pAdapt - Adapter structure
  29. ppVc - pointer to a pointer of Vc
  30. VcType - Type of VC to allocate (incoming, pmp outgoing etc)
  31. Return Value:
  32. NDIS_STATUS_SUCCESS if we could create a VC
  33. NDIS_STATUS_RESOURCES no resources
  34. NDIS_STATUS_CLOSING if we couldn't reference the adapter
  35. --*/
  36. {
  37. PATMSM_VC pVc;
  38. NDIS_STATUS Status;
  39. *ppVc = NULL;
  40. //
  41. // Add a reference to the adapter for the VC (see if the adapter
  42. // is closing)
  43. //
  44. if(!AtmSmReferenceAdapter(pAdapt))
  45. return NDIS_STATUS_CLOSING;
  46. //
  47. // Allocate a Vc, initialize it and link it into the Adapter
  48. //
  49. AtmSmAllocMem(&pVc, PATMSM_VC, sizeof(ATMSM_VC));
  50. if(NULL != pVc)
  51. {
  52. NdisZeroMemory(pVc, sizeof(ATMSM_VC));
  53. pVc->ulSignature = atmsm_vc_signature;
  54. pVc->NdisVcHandle = NdisVcHandle;
  55. pVc->pAdapt = pAdapt;
  56. pVc->ulRefCount = 1; // Dereferenced when DeleteVc is called.
  57. pVc->VcType = VcType;
  58. pVc->MaxSendSize = pAdapt->MaxPacketSize; // default
  59. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_IDLE);
  60. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  61. InsertHeadList(&pAdapt->InactiveVcHead, &pVc->List);
  62. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  63. Status = NDIS_STATUS_SUCCESS;
  64. DbgInfo(("CreateVc: Created Vc %x\n", pVc));
  65. }
  66. else
  67. {
  68. // Not enough resources, hence remove the reference we added above
  69. AtmSmDereferenceAdapter(pAdapt);
  70. Status = NDIS_STATUS_RESOURCES;
  71. DbgErr(("CreateVc: Failed - No resources\n"));
  72. }
  73. *ppVc = pVc;
  74. return Status;
  75. }
  76. BOOLEAN AtmSmReferenceVc(
  77. IN PATMSM_VC pVc
  78. )
  79. /*++
  80. Routine Description:
  81. Reference the VC.
  82. Arguments:
  83. pVc Pointer to the VC.
  84. Return Value:
  85. TRUE Referenced
  86. FALSE Interface is closing, cannot reference.
  87. --*/
  88. {
  89. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  90. BOOLEAN rc = FALSE;
  91. DbgInfo(("AtmSmReferenceVc - VC - 0x%X\n", pVc));
  92. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  93. if(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_CLOSING)
  94. {
  95. pVc->ulRefCount ++;
  96. rc = TRUE;
  97. }
  98. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  99. return rc;
  100. }
  101. ULONG AtmSmDereferenceVc(
  102. IN PATMSM_VC pVc
  103. )
  104. /*++
  105. Routine Description:
  106. Dereference the VC. This could result in the VC to be deallocated.
  107. Arguments:
  108. pVc Pointer to the VC.
  109. Return Value:
  110. Reference count
  111. --*/
  112. {
  113. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  114. ULONG ulRet;
  115. TraceIn(AtmSmDereferenceVc);
  116. DbgInfo(("AtmSmDereferenceVc - VC - 0x%X\n", pVc));
  117. ASSERT(pVc->ulRefCount > 0);
  118. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  119. ulRet = --pVc->ulRefCount;
  120. if(0 == pVc->ulRefCount)
  121. {
  122. PIRP pIrp;
  123. ULONG VcType = pVc->VcType;
  124. NDIS_HANDLE NdisVcHandle = pVc->NdisVcHandle;
  125. ASSERT (ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
  126. ASSERT (0 == pVc->ulNumTotalMembers);
  127. // cleanup a connectIrp if it exists
  128. pIrp = pVc->pConnectIrp;
  129. pVc->pConnectIrp = NULL;
  130. if(pIrp)
  131. {
  132. pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  133. pIrp->IoStatus.Information = 0;
  134. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  135. }
  136. // Remove any send packets pending on the Vc
  137. while(pVc->pSendPktNext)
  138. {
  139. PPROTO_RSVD pPRsvd;
  140. PNDIS_PACKET pPacket;
  141. pPacket = pVc->pSendPktNext;
  142. pPRsvd = GET_PROTO_RSVD(pPacket);
  143. pVc->pSendPktNext = pPRsvd->pPktNext;
  144. // this is the last packet
  145. if(pVc->pSendLastPkt == pPacket)
  146. pVc->pSendLastPkt = NULL;
  147. pVc->ulSendPktsCount--;
  148. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  149. AtmSmCoSendComplete(NDIS_STATUS_CLOSING, (NDIS_HANDLE)pVc, pPacket);
  150. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  151. }
  152. RemoveEntryList(&pVc->List);
  153. // this is important - since memory is not cleared
  154. pVc->ulSignature = atmsm_dead_vc_signature;
  155. pVc->pAdapt = NULL;
  156. AtmSmFreeMem(pVc);
  157. // Release the lock on the adapter
  158. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  159. if(((VC_TYPE_PP_OUTGOING == VcType) ||
  160. (VC_TYPE_PMP_OUTGOING == VcType)) &&
  161. NdisVcHandle != NULL)
  162. {
  163. (VOID)NdisCoDeleteVc(NdisVcHandle);
  164. }
  165. // dereference the adapter (to remove the VC reference)
  166. // should be done after releasing the lock
  167. AtmSmDereferenceAdapter(pAdapt);
  168. }
  169. else
  170. {
  171. // Release the lock on the adapter
  172. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  173. }
  174. TraceOut(AtmSmDereferenceVc);
  175. return ulRet;
  176. }
  177. BOOLEAN DeleteMemberInfoFromVc(
  178. IN PATMSM_VC pVc,
  179. IN PATMSM_PMP_MEMBER pMemberToRemove
  180. )
  181. /*++
  182. Routine Description:
  183. The specified member structure is removed from the VC and the
  184. structure is freed.
  185. Arguments:
  186. pVc Pointer to the VC.
  187. Return Value:
  188. TRUE - if removed
  189. FALSE - otherwise
  190. --*/
  191. {
  192. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  193. PATMSM_PMP_MEMBER pMember;
  194. PATMSM_PMP_MEMBER pPrevMember = NULL;
  195. TraceIn(DeleteMemberInfoFromVc);
  196. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  197. for(pMember = pVc->pPMPMembers; pMember;
  198. pPrevMember = pMember, pMember = pMember->pNext)
  199. if(pMember == pMemberToRemove)
  200. break;
  201. ASSERT(pMember);
  202. if(!pMember)
  203. {
  204. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  205. return FALSE;
  206. }
  207. if(!pPrevMember)
  208. {
  209. pVc->pPMPMembers = pMember->pNext;
  210. }
  211. else
  212. {
  213. pPrevMember->pNext = pMember->pNext;
  214. }
  215. AtmSmFreeMem(pMember);
  216. pVc->ulNumTotalMembers--;
  217. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  218. // Now dereference the VC
  219. AtmSmDereferenceVc(pVc);
  220. TraceOut(DeleteMemberInfoFromVc);
  221. return TRUE;
  222. }
  223. VOID AtmSmDisconnectVc(
  224. IN PATMSM_VC pVc
  225. )
  226. /*++
  227. Routine Description:
  228. This routine can be used to disconnect a P-P VC or disconnect
  229. all members of a PMP Vc
  230. Arguments:
  231. pVc - Pointer to the VC.
  232. Return Value:
  233. NONE
  234. --*/
  235. {
  236. NDIS_STATUS Status;
  237. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  238. TraceIn(AtmSmDisconnectVc);
  239. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  240. if(VC_TYPE_PMP_OUTGOING != pVc->VcType)
  241. {
  242. //
  243. // This is a PP VC
  244. //
  245. if((ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_SETUP_IN_PROGRESS) ||
  246. (ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_ACTIVE))
  247. {
  248. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSING);
  249. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  250. Status = NdisClCloseCall(
  251. pVc->NdisVcHandle,
  252. NULL, // No party Handle
  253. NULL, // No Buffer
  254. 0 // Size of above
  255. );
  256. if(NDIS_STATUS_PENDING != Status)
  257. {
  258. AtmSmCloseCallComplete(
  259. Status,
  260. (NDIS_HANDLE)pVc,
  261. (NDIS_HANDLE)NULL
  262. );
  263. }
  264. }
  265. else
  266. {
  267. if(ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_IDLE)
  268. {
  269. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  270. // remove the reference added to the VC while creating
  271. AtmSmDereferenceVc(pVc);
  272. }
  273. else
  274. {
  275. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  276. }
  277. }
  278. }
  279. else
  280. {
  281. PATMSM_PMP_MEMBER pMember;
  282. // this is a PMP VC
  283. //
  284. // Find a member that we haven't tried drop on.
  285. //
  286. while(TRUE)
  287. {
  288. for(pMember = pVc->pPMPMembers; pMember != NULL;
  289. pMember = pMember->pNext)
  290. {
  291. if(0 == (pMember->ulFlags & ATMSM_MEMBER_DROP_TRIED))
  292. {
  293. break;
  294. }
  295. }
  296. if(!pMember) // we are done with all members
  297. break;
  298. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  299. AtmSmDropMemberFromVc(pVc, pMember);
  300. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  301. }
  302. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  303. // remove the reference added to the VC while creating
  304. AtmSmDereferenceVc(pVc);
  305. }
  306. TraceOut(AtmSmDisconnectVc);
  307. }
  308. VOID AtmSmDropMemberFromVc(
  309. IN PATMSM_VC pVc,
  310. IN PATMSM_PMP_MEMBER pMemberToDrop
  311. )
  312. /*++
  313. Routine Description:
  314. This is used to drop a member from a PMP VC. This could be
  315. called as a result of incoming Drop request, or we are
  316. initiating a drop request.
  317. Handle all cases
  318. (a) Not connected to PMP Vc
  319. (b) Connection being setup (MakeCall or AddParty in progress)
  320. (c) Connected to PMP Vc
  321. Arguments:
  322. pVc - Pointer to the VC.
  323. pMemberToDrop - pointer to a member that is being dropped
  324. Return Value:
  325. NONE
  326. --*/
  327. {
  328. PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
  329. BOOLEAN bLockReleased = FALSE;
  330. NDIS_STATUS Status;
  331. NDIS_HANDLE NdisVcHandle;
  332. NDIS_HANDLE NdisPartyHandle;
  333. TraceIn(AtmSmDropMemberFromVc);
  334. DbgInfo(("pAdapt %x, pVc %x pMember %x, ConnSt %x, PartyHandle %x\n",
  335. pAdapt, pVc, pMemberToDrop, ATMSM_GET_MEMBER_STATE(pMemberToDrop),
  336. pMemberToDrop->NdisPartyHandle));
  337. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  338. pMemberToDrop->ulFlags |= ATMSM_MEMBER_DROP_TRIED;
  339. switch(ATMSM_GET_MEMBER_STATE(pMemberToDrop))
  340. {
  341. case ATMSM_MEMBER_CONNECTED:
  342. NdisPartyHandle = pMemberToDrop->NdisPartyHandle;
  343. ASSERT(NdisPartyHandle != NULL);
  344. if((pVc->ulNumActiveMembers + pVc->ulNumConnectingMembers)
  345. > 1)
  346. {
  347. //
  348. // This is not the last member in connected or connecting
  349. // state. Hence use DropParty.
  350. //
  351. ATMSM_SET_MEMBER_STATE(pMemberToDrop, ATMSM_MEMBER_CLOSING);
  352. pVc->ulNumActiveMembers--;
  353. pVc->ulNumDroppingMembers++;
  354. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  355. bLockReleased = TRUE;
  356. Status = NdisClDropParty(
  357. NdisPartyHandle,
  358. NULL,
  359. 0
  360. );
  361. if(NDIS_STATUS_PENDING != Status)
  362. {
  363. AtmSmDropPartyComplete(
  364. Status,
  365. (NDIS_HANDLE)pMemberToDrop
  366. );
  367. }
  368. }
  369. else
  370. {
  371. //
  372. // This is the last active party. Check if any DropParty()'s are
  373. // yet to finish.
  374. //
  375. if(0 != pVc->ulNumDroppingMembers)
  376. {
  377. //
  378. // This member will have to wait till all DropParty()s are
  379. // complete. Mark the ClusterControlVc so that we send
  380. // a CloseCall() when all DropParty()s are done.
  381. //
  382. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_NEED_CLOSING);
  383. }
  384. else
  385. {
  386. //
  387. // Last active party, and no DropParty pending.
  388. //
  389. NdisVcHandle = pVc->NdisVcHandle;
  390. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_CLOSING);
  391. ATMSM_SET_MEMBER_STATE(pMemberToDrop, ATMSM_MEMBER_CLOSING);
  392. pVc->ulNumActiveMembers--;
  393. pVc->ulNumDroppingMembers++;
  394. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  395. bLockReleased = TRUE;
  396. Status = NdisClCloseCall(
  397. NdisVcHandle,
  398. NdisPartyHandle,
  399. NULL,
  400. 0
  401. );
  402. if(NDIS_STATUS_PENDING != Status)
  403. {
  404. AtmSmCloseCallComplete(
  405. Status,
  406. (NDIS_HANDLE)pVc,
  407. (NDIS_HANDLE)pMemberToDrop
  408. );
  409. }
  410. }
  411. }
  412. break;
  413. case ATMSM_MEMBER_CONNECTING:
  414. //
  415. // Mark it so that we'll delete it when the AddParty/MakeCall
  416. // completes.
  417. //
  418. pMemberToDrop->ulFlags |= ATMSM_MEMBER_INVALID;
  419. break;
  420. case ATMSM_MEMBER_CLOSING:
  421. NOTHING;
  422. break;
  423. case ATMSM_MEMBER_IDLE:
  424. //
  425. // No connection. Just unlink this from the IntF and free it.
  426. //
  427. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  428. bLockReleased = TRUE;
  429. DeleteMemberInfoFromVc(pVc, pMemberToDrop);
  430. break;
  431. default:
  432. ASSERT(FALSE);
  433. break;
  434. }
  435. if(!bLockReleased)
  436. {
  437. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  438. }
  439. TraceOut(AtmSmDropMemberFromVc);
  440. }
  441. PCO_CALL_PARAMETERS AtmSmPrepareCallParameters(
  442. IN PATMSM_ADAPTER pAdapt,
  443. IN PHW_ADDR pHwAddr,
  444. IN BOOLEAN IsMakeCall,
  445. IN BOOLEAN IsMultipointVC
  446. )
  447. /*++
  448. Routine Description:
  449. Allocate and fill in call parameters for use in a MakeCall
  450. Arguments:
  451. pAdapt - Ptr to Adapter
  452. pHwAddr - Points to the Called ATM address and subaddress
  453. IsMakeCall - MakeCall or AddParty
  454. Return Value:
  455. Allocated Call Parameter
  456. --*/
  457. {
  458. PATMSM_FLOW_SPEC pFlowSpec;
  459. PCO_CALL_PARAMETERS pCallParameters;
  460. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  461. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  462. //
  463. // All Info Elements that we need to fill:
  464. //
  465. Q2931_IE UNALIGNED * pIe;
  466. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  467. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  468. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  469. ATM_BLLI_IE UNALIGNED * pBlli;
  470. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  471. ULONG RequestSize;
  472. RequestSize = sizeof(CO_CALL_PARAMETERS) +
  473. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  474. sizeof(Q2931_CALLMGR_PARAMETERS) +
  475. (IsMakeCall? ATMSM_MAKE_CALL_IE_SPACE :
  476. ATMSM_ADD_PARTY_IE_SPACE);
  477. AtmSmAllocMem(&pCallParameters, PCO_CALL_PARAMETERS, RequestSize);
  478. if(NULL == pCallParameters)
  479. {
  480. return(pCallParameters);
  481. }
  482. pFlowSpec = &(pAdapt->VCFlowSpec);
  483. //
  484. // Zero out everything
  485. //
  486. NdisZeroMemory((PUCHAR)pCallParameters, RequestSize);
  487. //
  488. // Distribute space amongst the various structures
  489. //
  490. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  491. ((PUCHAR)pCallParameters +
  492. sizeof(CO_CALL_PARAMETERS));
  493. //
  494. // Set pointers to link the above structures together
  495. //
  496. pCallParameters->CallMgrParameters = pCallMgrParameters;
  497. pCallParameters->MediaParameters = (PCO_MEDIA_PARAMETERS)NULL;
  498. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  499. pCallMgrParameters->CallMgrSpecific.Length =
  500. sizeof(Q2931_CALLMGR_PARAMETERS) +
  501. (IsMakeCall? ATMSM_MAKE_CALL_IE_SPACE :
  502. ATMSM_ADD_PARTY_IE_SPACE);
  503. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  504. pCallMgrParameters->CallMgrSpecific.Parameters;
  505. if(IsMultipointVC)
  506. pCallParameters->Flags |= MULTIPOINT_VC;
  507. //
  508. // Call Manager generic flow parameters:
  509. //
  510. pCallMgrParameters->Transmit.TokenRate = (pFlowSpec->SendBandwidth);
  511. pCallMgrParameters->Transmit.TokenBucketSize = (pFlowSpec->SendMaxSize);
  512. pCallMgrParameters->Transmit.MaxSduSize = pFlowSpec->SendMaxSize;
  513. pCallMgrParameters->Transmit.PeakBandwidth = (pFlowSpec->SendBandwidth);
  514. pCallMgrParameters->Transmit.ServiceType = pFlowSpec->ServiceType;
  515. //
  516. // We are setting up unidirectional calls, so receive side values are 0's.
  517. // Note: for PMP it should be 0 in all cases
  518. //
  519. pCallMgrParameters->Receive.ServiceType = pFlowSpec->ServiceType;
  520. //
  521. // Q2931 Call Manager Parameters:
  522. //
  523. //
  524. // Called address:
  525. //
  526. //
  527. pAtmCallMgrParameters->CalledParty = pHwAddr->Address;
  528. // NOTE: Add Called Subaddress IE for E164.
  529. //
  530. // Calling address:
  531. //
  532. pAtmCallMgrParameters->CallingParty = pAdapt->ConfiguredAddress;
  533. //
  534. // RFC 1755 (Sec 5) says that the following IEs MUST be present in the
  535. // SETUP message, so fill them all.
  536. //
  537. // AAL Parameters
  538. // Traffic Descriptor (MakeCall only)
  539. // Broadband Bearer Capability (MakeCall only)
  540. // Broadband Low Layer Info
  541. // QoS (MakeCall only)
  542. //
  543. //
  544. // Initialize the Info Element list
  545. //
  546. pAtmCallMgrParameters->InfoElementCount = 0;
  547. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  548. //
  549. // AAL Parameters:
  550. //
  551. {
  552. UNALIGNED AAL5_PARAMETERS *pAal5;
  553. pIe->IEType = IE_AALParameters;
  554. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  555. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  556. pAalIe->AALType = AAL_TYPE_AAL5;
  557. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  558. pAal5->ForwardMaxCPCSSDUSize = pFlowSpec->SendMaxSize;
  559. pAal5->BackwardMaxCPCSSDUSize = pFlowSpec->ReceiveMaxSize;
  560. }
  561. pAtmCallMgrParameters->InfoElementCount++;
  562. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  563. //
  564. // Traffic Descriptor:
  565. //
  566. if(IsMakeCall)
  567. {
  568. pIe->IEType = IE_TrafficDescriptor;
  569. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_TRAFFIC_DESCR_IE;
  570. pTrafficDescriptor = (PATM_TRAFFIC_DESCRIPTOR_IE)pIe->IE;
  571. if(SERVICETYPE_BESTEFFORT == pFlowSpec->ServiceType)
  572. {
  573. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  574. BYTES_TO_CELLS(pFlowSpec->SendBandwidth);
  575. pTrafficDescriptor->BestEffort = TRUE;
  576. }
  577. else
  578. {
  579. // Predictive/Guaranteed service
  580. // (we map this to CBR, see BBC below)
  581. pTrafficDescriptor->ForwardTD.PeakCellRateCLP01 =
  582. BYTES_TO_CELLS(pFlowSpec->SendBandwidth);
  583. pTrafficDescriptor->BestEffort = FALSE;
  584. }
  585. pAtmCallMgrParameters->InfoElementCount++;
  586. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  587. }
  588. //
  589. // Broadband Bearer Capability
  590. //
  591. if(IsMakeCall)
  592. {
  593. pIe->IEType = IE_BroadbandBearerCapability;
  594. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BBC_IE;
  595. pBbc = (PATM_BROADBAND_BEARER_CAPABILITY_IE)pIe->IE;
  596. pBbc->BearerClass = BCOB_X;
  597. pBbc->UserPlaneConnectionConfig = UP_P2P;
  598. if(SERVICETYPE_BESTEFFORT == pFlowSpec->ServiceType)
  599. {
  600. pBbc->TrafficType = TT_NOIND;
  601. pBbc->TimingRequirements = TR_NOIND;
  602. pBbc->ClippingSusceptability = CLIP_NOT;
  603. }
  604. else
  605. {
  606. pBbc->TrafficType = TT_CBR;
  607. pBbc->TimingRequirements = TR_END_TO_END;
  608. pBbc->ClippingSusceptability = CLIP_SUS;
  609. }
  610. pAtmCallMgrParameters->InfoElementCount++;
  611. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  612. }
  613. //
  614. // Broadband Lower Layer Information
  615. //
  616. pIe->IEType = IE_BLLI;
  617. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  618. pBlli = (PATM_BLLI_IE)pIe->IE;
  619. NdisMoveMemory((PUCHAR)pBlli,
  620. (PUCHAR)&AtmSmDefaultBlli,
  621. sizeof(ATM_BLLI_IE));
  622. pAtmCallMgrParameters->InfoElementCount++;
  623. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  624. //
  625. // QoS
  626. //
  627. if(IsMakeCall)
  628. {
  629. pIe->IEType = IE_QOSClass;
  630. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_QOS_IE;
  631. pQos = (PATM_QOS_CLASS_IE)pIe->IE;
  632. if(SERVICETYPE_BESTEFFORT == pFlowSpec->ServiceType)
  633. {
  634. pQos->QOSClassForward = pQos->QOSClassBackward = 0;
  635. }
  636. else
  637. {
  638. pQos->QOSClassForward = pQos->QOSClassBackward = 1;
  639. }
  640. pAtmCallMgrParameters->InfoElementCount++;
  641. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  642. }
  643. return(pCallParameters);
  644. }
  645. NTSTATUS VerifyRecvOpenContext(
  646. PATMSM_ADAPTER pAdapt
  647. )
  648. /*++
  649. Routine Description:
  650. This routine is used to verify that an open context passed is valid
  651. Note: we add a reference on the adapter
  652. Arguments:
  653. Return Value:
  654. --*/
  655. {
  656. NTSTATUS Status = STATUS_SUCCESS;
  657. PATMSM_ADAPTER pAdapter;
  658. ULONG ulNum = 0;
  659. if(pAdapt == NULL)
  660. {
  661. return STATUS_UNSUCCESSFUL;
  662. }
  663. ACQUIRE_GLOBAL_LOCK();
  664. // walk the adapter list to see if this adapter exists
  665. for(pAdapter = AtmSmGlobal.pAdapterList; pAdapter &&
  666. ulNum < AtmSmGlobal.ulAdapterCount;
  667. pAdapter = pAdapter->pAdapterNext)
  668. {
  669. if(pAdapt == pAdapter)
  670. break;
  671. }
  672. if(pAdapter == NULL || ulNum == AtmSmGlobal.ulAdapterCount)
  673. {
  674. RELEASE_GLOBAL_LOCK();
  675. return STATUS_UNSUCCESSFUL;
  676. }
  677. if(atmsm_adapter_signature != pAdapt->ulSignature)
  678. Status = STATUS_INVALID_PARAMETER;
  679. else
  680. {
  681. if(AtmSmReferenceAdapter(pAdapt))
  682. {
  683. if(FALSE == pAdapt->fAdapterOpenedForRecv)
  684. {
  685. Status = STATUS_INVALID_PARAMETER;
  686. // remove the reference
  687. AtmSmDereferenceAdapter(pAdapt);
  688. }
  689. }
  690. else
  691. Status = STATUS_UNSUCCESSFUL;
  692. }
  693. RELEASE_GLOBAL_LOCK();
  694. return Status;
  695. }
  696. NTSTATUS VerifyConnectContext(
  697. PATMSM_VC pVc
  698. )
  699. /*++
  700. Routine Description:
  701. This routine is used to verify that a connect context passed is valid
  702. Note: we add a reference on the VC
  703. Arguments:
  704. Return Value:
  705. --*/
  706. {
  707. NTSTATUS Status = STATUS_SUCCESS;
  708. try
  709. {
  710. if((atmsm_vc_signature != pVc->ulSignature) ||
  711. (NULL == pVc->pAdapt))
  712. Status = STATUS_INVALID_PARAMETER;
  713. else
  714. {
  715. if(!AtmSmReferenceVc(pVc))
  716. Status = STATUS_UNSUCCESSFUL;
  717. else
  718. {
  719. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  720. if(atmsm_adapter_signature != pAdapt->ulSignature)
  721. {
  722. Status = STATUS_INVALID_PARAMETER;
  723. // remove the VC reference
  724. AtmSmDereferenceVc(pVc);
  725. }
  726. }
  727. }
  728. }except(EXCEPTION_EXECUTE_HANDLER)
  729. {
  730. Status = GetExceptionCode();
  731. DbgErr(("VerifyConnectContext: CC 0x%x exception - 0x%x\n",
  732. pVc, Status));
  733. return Status;
  734. }
  735. return Status;
  736. }
  737. UINT CopyPacketToIrp(
  738. PIRP pIrp,
  739. PNDIS_PACKET pPkt
  740. )
  741. /*++
  742. Routine Description:
  743. This routine is used to copy the connects of a packet into the user supplied
  744. buffer.
  745. Arguments:
  746. Return Value:
  747. --*/
  748. {
  749. PNDIS_BUFFER pPktBuffer;
  750. PVOID pPktBufferVA, pDstBufferVA;
  751. UINT uiBufSize, uiTotalLen, uiMdlSizeLeft;
  752. UINT uiCopySize, uiTotalBytesCopied;
  753. NdisGetFirstBufferFromPacketSafe(pPkt,
  754. &pPktBuffer,
  755. &pPktBufferVA,
  756. &uiBufSize,
  757. &uiTotalLen,
  758. NormalPagePriority);
  759. if (pPktBufferVA == NULL)
  760. {
  761. return 0;
  762. }
  763. ASSERT(pPktBuffer && (0 != uiBufSize));
  764. uiTotalBytesCopied = 0;
  765. uiMdlSizeLeft = MmGetMdlByteCount(pIrp->MdlAddress);
  766. pDstBufferVA = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
  767. if(pDstBufferVA != NULL && uiMdlSizeLeft != 0)
  768. {
  769. while(pPktBuffer)
  770. {
  771. uiCopySize = (uiMdlSizeLeft < uiBufSize) ? uiMdlSizeLeft :uiBufSize;
  772. // copy the data
  773. NdisMoveMemory(pDstBufferVA, pPktBufferVA, uiCopySize);
  774. pDstBufferVA = (PVOID) ((PCHAR)pDstBufferVA + uiCopySize);
  775. uiTotalBytesCopied += uiCopySize;
  776. uiMdlSizeLeft -= uiCopySize;
  777. if(uiMdlSizeLeft <= 0)
  778. break;
  779. // get the next buffer
  780. NdisGetNextBuffer(pPktBuffer, &pPktBuffer);
  781. // get details of the new buffer
  782. if(pPktBuffer)
  783. {
  784. NdisQueryBufferSafe(pPktBuffer, &pPktBufferVA, &uiBufSize, NormalPagePriority);
  785. if(pPktBufferVA == NULL)
  786. break;
  787. }
  788. }
  789. }
  790. return uiTotalBytesCopied;
  791. }
  792. VOID AtmSmRecvReturnTimerFunction (
  793. IN PVOID SystemSpecific1,
  794. IN PVOID FunctionContext,
  795. IN PVOID SystemSpecific2,
  796. IN PVOID SystemSpecific3
  797. )
  798. /*++
  799. Routine Description:
  800. This timer function, checks to see there are any buffered packets that has
  801. been around for a while. If so it gives the packet back to the miniport
  802. driver.
  803. It queues itself back if there are anymore packets in the queue
  804. We use NdisGetSystemUpTime, since that is all the resolution we want
  805. Arguments:
  806. SystemSpecific1 - Not used
  807. FunctionContext - Adapter
  808. SystemSpecific2 - Not used
  809. SystemSpecific3 - Not used
  810. Return Value:
  811. None.
  812. --*/
  813. {
  814. PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)FunctionContext;
  815. ULONG ulTime;
  816. BOOLEAN bShouldQueueTimerAgain = FALSE;
  817. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  818. pAdapt->fRecvTimerQueued = FALSE;
  819. NdisGetSystemUpTime(&ulTime);
  820. // check if any packets have been sitting around for long
  821. // if so, return them
  822. while(pAdapt->pRecvPktNext)
  823. {
  824. PPROTO_RSVD pPRsvd;
  825. PNDIS_PACKET pPkt;
  826. pPkt = pAdapt->pRecvPktNext;
  827. pPRsvd = GET_PROTO_RSVD(pPkt);
  828. if((ulTime - pPRsvd->ulTime) >= RECV_BUFFERING_TIME)
  829. {
  830. pAdapt->pRecvPktNext = pPRsvd->pPktNext;
  831. if(pAdapt->pRecvLastPkt == pPkt)
  832. pAdapt->pRecvLastPkt = NULL;
  833. DbgVeryLoud(("Returning a packet that was buffered too long\n"));
  834. pAdapt->ulRecvPktsCount--;
  835. // release the recv queue lock
  836. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  837. // return the packet to the miniport
  838. NdisReturnPackets(&pPkt, 1);
  839. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  840. }
  841. else
  842. {
  843. // time hasn't expired for this packet
  844. ulTime = RECV_BUFFERING_TIME - (ulTime - pPRsvd->ulTime);
  845. bShouldQueueTimerAgain = TRUE;
  846. break;
  847. }
  848. }
  849. if(bShouldQueueTimerAgain)
  850. {
  851. SET_ADAPTER_RECV_TIMER(pAdapt, ulTime);
  852. }
  853. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  854. return;
  855. }
  856. VOID AtmSmConnectToPMPDestinations(
  857. IN PATMSM_VC pVc
  858. )
  859. /*++
  860. Routine Description:
  861. This will make a call to the destination in PMP case. It will MakeCall
  862. to the first member. Subsequent destinations are added using AddParty.
  863. Arguments:
  864. pVc - Ptr to a PMP Vc
  865. Return Value:
  866. None
  867. --*/
  868. {
  869. PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
  870. BOOLEAN bLockReleased = FALSE;
  871. PCO_CALL_PARAMETERS pCallParameters;
  872. NDIS_HANDLE ProtocolVcContext;
  873. NDIS_HANDLE ProtocolPartyContext;
  874. NDIS_STATUS Status;
  875. PATMSM_PMP_MEMBER pMember;
  876. TraceIn(AtmSmConnectToPMPDestinations);
  877. ASSERT(VC_TYPE_PMP_OUTGOING == pVc->VcType);
  878. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  879. do
  880. { // break off loop
  881. // First find any member addresses that is not yet connected
  882. for(pMember = pVc->pPMPMembers; pMember; pMember = pMember->pNext)
  883. if(ATMSM_GET_MEMBER_STATE(pMember) == ATMSM_MEMBER_IDLE)
  884. break;
  885. // if there are no - more members to be connected then get out
  886. if(!pMember)
  887. {
  888. break;
  889. }
  890. ProtocolVcContext = (NDIS_HANDLE)pVc;
  891. ProtocolPartyContext = (NDIS_HANDLE)pMember;
  892. //
  893. // First see if we have connected 1 or more members
  894. //
  895. if(0 == pVc->ulNumActiveMembers)
  896. {
  897. // No one is connected yet, so do a MakeCall
  898. ASSERT(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
  899. if(NULL == pVc->NdisVcHandle)
  900. {
  901. Status = NdisCoCreateVc(
  902. pAdapt->NdisBindingHandle,
  903. pAdapt->NdisAfHandle,
  904. (NDIS_HANDLE)pVc,
  905. &pVc->NdisVcHandle
  906. );
  907. if(NDIS_STATUS_SUCCESS != Status)
  908. {
  909. break;
  910. }
  911. DbgVeryLoud(("AddMembers: Created VC, VC %x, NdisVcHandle %x\n",
  912. pVc, pVc->NdisVcHandle));
  913. }
  914. ASSERT(NULL != pVc->NdisVcHandle);
  915. pCallParameters = AtmSmPrepareCallParameters(pAdapt,
  916. &pMember->HwAddr,
  917. TRUE,
  918. TRUE);
  919. if(pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  920. {
  921. Status = NdisCoDeleteVc(pVc->NdisVcHandle);
  922. ASSERT(NDIS_STATUS_SUCCESS == Status);
  923. pVc->NdisVcHandle = NULL;
  924. Status = NDIS_STATUS_RESOURCES;
  925. break;
  926. }
  927. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_SETUP_IN_PROGRESS);
  928. ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_CONNECTING);
  929. pVc->ulNumConnectingMembers++;
  930. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  931. bLockReleased = TRUE;
  932. Status = NdisClMakeCall(
  933. pVc->NdisVcHandle,
  934. pCallParameters,
  935. ProtocolPartyContext,
  936. &pMember->NdisPartyHandle
  937. );
  938. if(NDIS_STATUS_PENDING != Status)
  939. {
  940. AtmSmMakeCallComplete(
  941. Status,
  942. ProtocolVcContext,
  943. pMember->NdisPartyHandle,
  944. pCallParameters
  945. );
  946. }
  947. }
  948. else
  949. {
  950. // we have atleast one connected member, add the rest using AddParty
  951. ASSERT(NULL != pVc->NdisVcHandle);
  952. pCallParameters = AtmSmPrepareCallParameters(pAdapt,
  953. &pMember->HwAddr,
  954. FALSE,
  955. TRUE);
  956. if(pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  957. {
  958. Status = NDIS_STATUS_RESOURCES;
  959. break;
  960. }
  961. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_ADDING_PARTIES);
  962. ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_CONNECTING);
  963. pVc->ulNumConnectingMembers++;
  964. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  965. bLockReleased = TRUE;
  966. Status = NdisClAddParty(
  967. pVc->NdisVcHandle,
  968. ProtocolPartyContext,
  969. pCallParameters,
  970. &pMember->NdisPartyHandle
  971. );
  972. if(NDIS_STATUS_PENDING != Status)
  973. {
  974. AtmSmAddPartyComplete(
  975. Status,
  976. ProtocolPartyContext,
  977. pMember->NdisPartyHandle,
  978. pCallParameters
  979. );
  980. }
  981. }
  982. }while(FALSE);
  983. if(!bLockReleased)
  984. {
  985. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  986. }
  987. if(pVc->ulNumActiveMembers &&
  988. (pVc->ulNumActiveMembers == pVc->ulNumTotalMembers))
  989. {
  990. PIRP pIrp;
  991. //
  992. // 1 or more members are connected, send any packets pending on the VC.
  993. //
  994. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  995. DbgInfo(("PMP VC 0x%x connected - %u members\n", pVc,
  996. pVc->ulNumActiveMembers));
  997. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_ACTIVE);
  998. // now complete IRP that started this connect call
  999. pIrp = pVc->pConnectIrp;
  1000. pVc->pConnectIrp = NULL;
  1001. ASSERT(pIrp);
  1002. // remove the Vc from the inactive list
  1003. RemoveEntryList(&pVc->List);
  1004. // insert the vc into the active list
  1005. InsertHeadList(&pAdapt->ActiveVcHead, &pVc->List);
  1006. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  1007. if(pIrp)
  1008. {
  1009. pIrp->IoStatus.Status = STATUS_SUCCESS;
  1010. // now set the connect context
  1011. *(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer) = (HANDLE)pVc;
  1012. pIrp->IoStatus.Information = sizeof(HANDLE);
  1013. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  1014. }
  1015. AtmSmSendQueuedPacketsOnVc(pVc);
  1016. }
  1017. else
  1018. {
  1019. if(0 == pVc->ulNumTotalMembers)
  1020. {
  1021. // now complete IRP that started this connect call
  1022. PIRP pIrp = pVc->pConnectIrp;
  1023. pVc->pConnectIrp = NULL;
  1024. ASSERT(pIrp);
  1025. if(pIrp)
  1026. {
  1027. pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  1028. pIrp->IoStatus.Information = 0;
  1029. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  1030. }
  1031. DbgInfo(("PMP VC 0x%x failed to connect any members\n", pVc));
  1032. // Cleanup the VC - remove the reference added at create
  1033. AtmSmDereferenceVc(pVc);
  1034. }
  1035. }
  1036. TraceOut(AtmSmConnectToPMPDestinations);
  1037. }
  1038. VOID AtmSmConnectPPVC(
  1039. IN PATMSM_VC pVc
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This will make a call to the destination in PP case. It will MakeCall
  1044. to the destination.
  1045. Arguments:
  1046. pVc - Ptr to a PP Vc
  1047. Return Value:
  1048. None
  1049. --*/
  1050. {
  1051. PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)pVc->pAdapt;
  1052. BOOLEAN bLockReleased = FALSE;
  1053. PCO_CALL_PARAMETERS pCallParameters;
  1054. NDIS_HANDLE ProtocolVcContext;
  1055. NDIS_STATUS Status;
  1056. TraceIn(AtmSmConnectPPVC);
  1057. ASSERT(VC_TYPE_PP_OUTGOING == pVc->VcType);
  1058. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  1059. do
  1060. { // break off loop
  1061. ProtocolVcContext = (NDIS_HANDLE)pVc;
  1062. ASSERT(ATMSM_GET_VC_STATE(pVc) != ATMSM_VC_ACTIVE);
  1063. ASSERT(NULL == pVc->NdisVcHandle);
  1064. if(NULL == pVc->NdisVcHandle)
  1065. {
  1066. Status = NdisCoCreateVc(
  1067. pAdapt->NdisBindingHandle,
  1068. pAdapt->NdisAfHandle,
  1069. (NDIS_HANDLE)pVc,
  1070. &pVc->NdisVcHandle
  1071. );
  1072. if(NDIS_STATUS_SUCCESS != Status)
  1073. {
  1074. break;
  1075. }
  1076. DbgVeryLoud(("Connect: Created VC, VC %x, NdisVcHandle %x\n",
  1077. pVc, pVc->NdisVcHandle));
  1078. }
  1079. ASSERT(NULL != pVc->NdisVcHandle);
  1080. pCallParameters = AtmSmPrepareCallParameters(pAdapt,
  1081. &pVc->HwAddr,
  1082. TRUE,
  1083. FALSE);
  1084. if(pCallParameters == (PCO_CALL_PARAMETERS)NULL)
  1085. {
  1086. Status = NdisCoDeleteVc(pVc->NdisVcHandle);
  1087. pVc->NdisVcHandle = NULL;
  1088. Status = NDIS_STATUS_RESOURCES;
  1089. break;
  1090. }
  1091. ATMSM_SET_VC_STATE(pVc, ATMSM_VC_SETUP_IN_PROGRESS);
  1092. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  1093. bLockReleased = TRUE;
  1094. Status = NdisClMakeCall(
  1095. pVc->NdisVcHandle,
  1096. pCallParameters,
  1097. NULL,
  1098. NULL
  1099. );
  1100. if(NDIS_STATUS_PENDING != Status)
  1101. {
  1102. AtmSmMakeCallComplete(
  1103. Status,
  1104. ProtocolVcContext,
  1105. NULL,
  1106. pCallParameters
  1107. );
  1108. }
  1109. }while(FALSE);
  1110. if(!bLockReleased)
  1111. {
  1112. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  1113. }
  1114. TraceOut(AtmSmConnectPPVC);
  1115. }