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.

1756 lines
49 KiB

  1. /*++
  2. Copyright (c) 1995-1996 Microsoft Corporation
  3. Module Name:
  4. pxdown.c
  5. Abstract:
  6. The module contains the calls to NDIS for the NDIS Proxy.
  7. Author:
  8. Richard Machin (RMachin)
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. RMachin 10-3-96 created
  13. TonyBe 02-21-99 re-work/re-write
  14. Notes:
  15. --*/
  16. #include "precomp.h"
  17. #include <atm.h>
  18. #define MODULE_NUMBER MODULE_CO
  19. #define _FILENUMBER 'OCXP'
  20. VOID
  21. PxCoBindAdapter(
  22. OUT PNDIS_STATUS pStatus,
  23. IN NDIS_HANDLE BindContext,
  24. IN PNDIS_STRING DeviceName,
  25. IN PVOID SystemSpecific1,
  26. IN PVOID SystemSpecific2
  27. )
  28. /*++
  29. Routine Description:
  30. Entry point that gets called by NDIS when an adapter appears on the
  31. system.
  32. Arguments:
  33. pStatus - place for our Return Value
  34. BindContext - to be used if we call NdisCompleteBindAdapter; we don't
  35. DeviceName - Name of the adapter to be bound to
  36. SystemSpecific1 - Name of the protocol-specific entry in this adapter's
  37. registry section
  38. SystemSpecific2 - Not used
  39. Return Value:
  40. None. We set *pStatus to NDIS_STATUS_SUCCESS if everything goes off well,
  41. otherwise an NDIS error status.
  42. --*/
  43. {
  44. NDIS_STATUS OpenError;
  45. UINT SelectedIndex;
  46. PPX_ADAPTER pAdapter = NULL;
  47. NDIS_MEDIUM Media[NdisMediumMax];
  48. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  49. ULONG InitStage = 0;
  50. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxCoBindAdapter: %Z\n", DeviceName));
  51. //
  52. // Wait for all calls to NdisRegisterProtocol to complete.
  53. //
  54. NdisWaitEvent(&DeviceExtension->NdisEvent, 0);
  55. //
  56. // Use a do..while..false loop and break on error.
  57. // Cleanup is at the end of the loop.
  58. //
  59. do
  60. {
  61. //
  62. // Check if this is a device we have already bound to.
  63. //
  64. if (PxIsAdapterAlreadyBound(DeviceName)) {
  65. Status = NDIS_STATUS_NOT_ACCEPTED;
  66. PXDEBUGP(PXD_WARNING, PXM_CO, ("PxCoBindAdapter: already bound to %Z\n", DeviceName));
  67. break;
  68. }
  69. // pAdapter gets the devicname stuck on the end -- alloc space for it
  70. //
  71. pAdapter =
  72. PxAllocateAdapter(DeviceName->MaximumLength);
  73. if(pAdapter == (PPX_ADAPTER)NULL) {
  74. Status = NDIS_STATUS_RESOURCES;
  75. break;
  76. }
  77. //
  78. // We have memory allocated we will need to free it!
  79. //
  80. InitStage++;
  81. //
  82. // Go to the end of the string and work back until we find
  83. // the first "{". Now start parsing the string converting
  84. // and copying from WCHAR to CHAR all digits until we hit
  85. // the closing "}".
  86. //
  87. {
  88. ULONG i;
  89. for (i = DeviceName->Length/2; i > 0; i--) {
  90. if (DeviceName->Buffer[i] == (WCHAR)L'{') {
  91. break;
  92. }
  93. }
  94. if (i != 0) {
  95. NDIS_STRING Src;
  96. RtlInitUnicodeString(&Src, &DeviceName->Buffer[i]);
  97. RtlGUIDFromString(&Src, &pAdapter->Guid);
  98. PXDEBUGP(PXD_INFO, PXM_CO, ("GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
  99. pAdapter->Guid.Data1, pAdapter->Guid.Data2, pAdapter->Guid.Data3,
  100. pAdapter->Guid.Data4[0],pAdapter->Guid.Data4[1],pAdapter->Guid.Data4[2],
  101. pAdapter->Guid.Data4[3],pAdapter->Guid.Data4[4],pAdapter->Guid.Data4[5],
  102. pAdapter->Guid.Data4[6],pAdapter->Guid.Data4[7]));
  103. }
  104. }
  105. PxInitBlockStruc(&pAdapter->BindEvent);
  106. PxInitBlockStruc(&pAdapter->OpenEvent); //blocks thread
  107. PxInitBlockStruc(&pAdapter->AfRegisterEvent);
  108. pAdapter->AfRegisteringCount = 0;
  109. //
  110. // We can't get away with a single open for both
  111. // client and call manager components without changing the wrapper.
  112. // Bite the bullet and do two opens.
  113. //
  114. //
  115. // Build the medium array
  116. //
  117. {
  118. ULONG i;
  119. for (i = 0; i < NdisMediumMax; i++) {
  120. Media[i] = i;
  121. }
  122. }
  123. //
  124. // Open the adapter as a client!
  125. //
  126. NdisOpenAdapter(&Status,
  127. &OpenError,
  128. &pAdapter->ClBindingHandle,
  129. &SelectedIndex,
  130. Media,
  131. NdisMediumMax,
  132. DeviceExtension->PxProtocolHandle,
  133. (NDIS_HANDLE)pAdapter,
  134. DeviceName,
  135. 0,
  136. NULL);
  137. if(Status == NDIS_STATUS_PENDING) {
  138. Status = PxBlock(&pAdapter->OpenEvent);
  139. }
  140. if(Status != NDIS_STATUS_SUCCESS) {
  141. // We had some sort of error
  142. PXDEBUGP(PXD_ERROR, PXM_CO, ("Cl OpenAdapter Failed %x\n", Status));
  143. pAdapter->ClBindingHandle = NULL;
  144. pAdapter->MediaType = -1;
  145. break;
  146. }
  147. NdisAcquireSpinLock(&pAdapter->Lock);
  148. REF_ADAPTER(pAdapter);
  149. NdisReleaseSpinLock(&pAdapter->Lock);
  150. //
  151. // We have a ref on the adapter
  152. //
  153. InitStage++;
  154. PxInitBlockStruc(&pAdapter->OpenEvent); //blocks thread
  155. //
  156. // Open the adapter as a call manager!
  157. //
  158. NdisOpenAdapter(&Status,
  159. &OpenError,
  160. &pAdapter->CmBindingHandle,
  161. &SelectedIndex,
  162. Media,
  163. NdisMediumMax,
  164. DeviceExtension->PxProtocolHandle,
  165. (NDIS_HANDLE)&pAdapter->Sig,
  166. DeviceName,
  167. 0,
  168. NULL);
  169. if(Status == NDIS_STATUS_PENDING) {
  170. Status = PxBlock(&pAdapter->OpenEvent);
  171. }
  172. if(Status != NDIS_STATUS_SUCCESS) {
  173. // We had some sort of error
  174. pAdapter->CmBindingHandle = NULL;
  175. pAdapter->MediaType = -1;
  176. PXDEBUGP(PXD_ERROR, PXM_CO, ("CM OpenAdapter Failed %x\n", Status));
  177. break;
  178. }
  179. NdisAcquireSpinLock(&pAdapter->Lock);
  180. REF_ADAPTER(pAdapter);
  181. //
  182. // We have another ref on the adapter
  183. //
  184. InitStage++;
  185. pAdapter->State = PX_ADAPTER_OPEN;
  186. PXDEBUGP(PXD_INFO, PXM_CO, ("Bound to %Z, Adapter %p, NdisHandle %p\n",
  187. DeviceName, pAdapter, pAdapter->ClBindingHandle));
  188. //
  189. // Set up media type in adapters
  190. //
  191. pAdapter->MediaType =
  192. Media[SelectedIndex];
  193. NdisReleaseSpinLock(&pAdapter->Lock);
  194. //
  195. // Set MediaTypeName/MediaSubtypeName for this adapter
  196. //
  197. {
  198. NDIS_WAN_MEDIUM_SUBTYPE SubType = 0;
  199. PX_REQUEST ProxyRequest;
  200. PNDIS_REQUEST Request;
  201. PWCHAR MediaTypes[] = {
  202. L"GENERIC",
  203. L"X25",
  204. L"ISDN",
  205. L"SERIAL",
  206. L"FRAMERELAY",
  207. L"ATM",
  208. L"SONET",
  209. L"SW56",
  210. L"PPTP VPN",
  211. L"L2TP VPN",
  212. L"IRDA",
  213. L"PARALLEL"};
  214. switch (pAdapter->MediaType) {
  215. case NdisMediumWan:
  216. case NdisMediumCoWan:
  217. PxInitBlockStruc (&ProxyRequest.Block);
  218. Request = &ProxyRequest.NdisRequest;
  219. Request->RequestType =
  220. NdisRequestQueryInformation;
  221. Request->DATA.QUERY_INFORMATION.Oid =
  222. OID_WAN_MEDIUM_SUBTYPE;
  223. Request->DATA.QUERY_INFORMATION.InformationBuffer =
  224. &SubType;
  225. Request->DATA.QUERY_INFORMATION.InformationBufferLength =
  226. sizeof(NDIS_WAN_MEDIUM_SUBTYPE);
  227. NdisRequest(&Status,
  228. pAdapter->ClBindingHandle,
  229. Request);
  230. if (Status == NDIS_STATUS_PENDING) {
  231. Status = PxBlock(&ProxyRequest.Block);
  232. }
  233. if (Status != NDIS_STATUS_SUCCESS) {
  234. SubType = 0;
  235. }
  236. break;
  237. case NdisMediumAtm:
  238. SubType = NdisWanMediumAtm;
  239. break;
  240. default:
  241. SubType = NdisWanMediumHub;
  242. break;
  243. }
  244. if ((ULONG)SubType > 11) {
  245. SubType = 0;
  246. }
  247. pAdapter->MediumSubType = SubType;
  248. NdisMoveMemory((PUCHAR)(pAdapter->MediaName),
  249. (PUCHAR)(MediaTypes[SubType]),
  250. wcslen(MediaTypes[SubType]) * sizeof(WCHAR));
  251. pAdapter->MediaNameLength =
  252. wcslen(MediaTypes[SubType]) * sizeof(WCHAR);
  253. Status = NDIS_STATUS_SUCCESS;
  254. }
  255. //
  256. // Stick the binding name string in the adapter. We use in subsequent
  257. // checks that we're not already bound.
  258. //
  259. pAdapter->DeviceName.MaximumLength = DeviceName->MaximumLength;
  260. pAdapter->DeviceName.Length = DeviceName->Length;
  261. pAdapter->DeviceName.Buffer =
  262. (PWCHAR)((PUCHAR)pAdapter + sizeof(PX_ADAPTER));
  263. NdisMoveMemory(pAdapter->DeviceName.Buffer,
  264. DeviceName->Buffer,
  265. DeviceName->Length);
  266. } while(FALSE); //end of do loop
  267. if (pAdapter != NULL) {
  268. PxSignal(&pAdapter->BindEvent, NDIS_STATUS_SUCCESS);
  269. }
  270. if (Status != NDIS_STATUS_SUCCESS) {
  271. //
  272. // Set the state to closing since we're going to get rid
  273. // of the adapter.
  274. //
  275. if ((InitStage >= 1) && (InitStage <= 3)) {
  276. pAdapter->State = PX_ADAPTER_CLOSING;
  277. }
  278. switch (InitStage) {
  279. case 3:
  280. //
  281. // We have applied 2 additional refs on the adapter
  282. // we don't need to do the entire deref code for
  283. // the first one! Fall through to the case below
  284. // to run the full deref code for the second ref.
  285. //
  286. pAdapter->RefCount--;
  287. case 2:
  288. //
  289. // We have added at least one ref that will need
  290. // the entire deref package applied! Break out
  291. // so the deref code can free the memory.
  292. //
  293. PxInitBlockStruc(&pAdapter->ClCloseEvent);
  294. NdisCloseAdapter(&Status, pAdapter->ClBindingHandle);
  295. if (Status == NDIS_STATUS_PENDING) {
  296. Status = PxBlock(&pAdapter->ClCloseEvent);
  297. }
  298. DEREF_ADAPTER(pAdapter);
  299. break;
  300. case 1:
  301. //
  302. // We have added no addition refs so we can
  303. // just free the memory here.
  304. //
  305. PxFreeAdapter(pAdapter);
  306. break;
  307. default:
  308. break;
  309. }
  310. }
  311. ASSERT(Status != NDIS_STATUS_PENDING);
  312. *pStatus = Status;
  313. }
  314. VOID
  315. PxCoOpenAdaperComplete(
  316. NDIS_HANDLE BindingContext,
  317. NDIS_STATUS Status,
  318. NDIS_STATUS OpenErrorStatus
  319. )
  320. /*++
  321. Routine Description
  322. Our OpenAdapter completion . We signal whoever opened the
  323. adapter.
  324. Arguments
  325. BindingContext - A pointer to a PX_ADAPTER structure.
  326. Status - Status of open attempt.
  327. OpenErrorStatus - Additional status information.
  328. Return Value:
  329. None
  330. --*/
  331. {
  332. PPX_ADAPTER pAdapter;
  333. BOOLEAN IsClient;
  334. PXDEBUGP(PXD_LOUD, PXM_CO, ("Open Adapter Complete %p %x\n", BindingContext, Status));
  335. AdapterFromBindContext(BindingContext, pAdapter, IsClient);
  336. PxSignal(&pAdapter->OpenEvent, Status);
  337. }
  338. VOID
  339. PxCoUnbindAdapter(
  340. OUT PNDIS_STATUS pStatus,
  341. IN NDIS_HANDLE ProtocolBindContext,
  342. IN PNDIS_HANDLE UnbindContext
  343. )
  344. /*++
  345. Routine Description:
  346. entry point called by NDIS when we need to destroy an existing
  347. adapter binding. This is called for the CM open.
  348. By now, al clients will have been called. So any clients that opend this AF will have cleaned up their
  349. connections with us, and we will have cleaned up with the Call Manager.
  350. We should have CL and related CL adapter structures to get rid of. The Client Bind, SAPs, VCs and Party structures
  351. should already have gone. If not, we throw them away anyway.
  352. Close and clean up the adapters.
  353. Arguments:
  354. pStatus - where we return the status of this call
  355. ProtocolBindContext - actually a pointer to the Adapter structure
  356. UnbindContext - we should pass this value in NdisCompleteUnbindAdapter
  357. Return Value:
  358. None; *pStatus contains the result code.
  359. --*/
  360. {
  361. PPX_ADAPTER pAdapter;
  362. NDIS_STATUS Status;
  363. BOOLEAN IsClient;
  364. AdapterFromBindContext(ProtocolBindContext, pAdapter, IsClient);
  365. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxCoUnbindAdapter: pAdapter %p, UnbindContext %p\n",
  366. pAdapter, UnbindContext));
  367. PxBlock(&pAdapter->BindEvent);
  368. NdisAcquireSpinLock(&pAdapter->Lock);
  369. pAdapter->UnbindContext = UnbindContext;
  370. pAdapter->State = PX_ADAPTER_CLOSING;
  371. //
  372. // Wait for any threads registering AFs to exit.
  373. //
  374. while (pAdapter->AfRegisteringCount != 0) {
  375. NdisReleaseSpinLock(&pAdapter->Lock);
  376. PxBlock(&pAdapter->AfRegisterEvent);
  377. NdisAcquireSpinLock(&pAdapter->Lock);
  378. }
  379. ASSERT((pAdapter->Flags & PX_CMAF_REGISTERING) == 0);
  380. //
  381. // Do we have any af's opend on the underlying call manager
  382. // and are there any saps registered on them?
  383. //
  384. while (!IsListEmpty(&pAdapter->ClAfList)) {
  385. PPX_TAPI_PROVIDER TapiProvider;
  386. PPX_CL_AF pClAf;
  387. pClAf = (PPX_CL_AF)RemoveHeadList(&pAdapter->ClAfList);
  388. InsertTailList(&pAdapter->ClAfClosingList, &pClAf->Linkage);
  389. NdisReleaseSpinLock(&pAdapter->Lock);
  390. NdisAcquireSpinLock(&pClAf->Lock);
  391. pClAf->State = PX_AF_CLOSING;
  392. TapiProvider = pClAf->TapiProvider;
  393. NdisReleaseSpinLock(&pClAf->Lock);
  394. //
  395. // Take all tapi devices associated with
  396. // this address family offline
  397. //
  398. if (TapiProvider != NULL) {
  399. NdisAcquireSpinLock(&TapiProvider->Lock);
  400. MarkProviderOffline(TapiProvider);
  401. NdisReleaseSpinLock(&TapiProvider->Lock);
  402. }
  403. //
  404. // Build list of Vc's that need attention
  405. //
  406. NdisAcquireSpinLock(&pClAf->Lock);
  407. while (!IsListEmpty(&pClAf->VcList)) {
  408. PLIST_ENTRY Entry;
  409. PPX_VC pActiveVc;
  410. Entry = RemoveHeadList(&pClAf->VcList);
  411. InsertHeadList(&pClAf->VcClosingList, Entry);
  412. pActiveVc = CONTAINING_RECORD(Entry, PX_VC, ClAfLinkage);
  413. NdisReleaseSpinLock(&pClAf->Lock);
  414. NdisAcquireSpinLock(&pActiveVc->Lock);
  415. pActiveVc->CloseFlags |= PX_VC_UNBIND;
  416. REF_VC(pActiveVc);
  417. PxVcCleanup(pActiveVc, 0);
  418. DEREF_VC_LOCKED(pActiveVc);
  419. NdisAcquireSpinLock(&pClAf->Lock);
  420. }
  421. //
  422. // get rid of any saps on this af
  423. //
  424. {
  425. PLIST_ENTRY pe;
  426. PPX_CL_SAP pClSap;
  427. pe = pClAf->ClSapList.Flink;
  428. pClSap =
  429. CONTAINING_RECORD(pe, PX_CL_SAP, Linkage);
  430. while ((PVOID)pClSap != (PVOID)&pClAf->ClSapList) {
  431. if (InterlockedCompareExchange((PLONG)&pClSap->State,
  432. PX_SAP_CLOSING,
  433. PX_SAP_OPENED) == PX_SAP_OPENED) {
  434. RemoveEntryList(&pClSap->Linkage);
  435. InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
  436. NdisReleaseSpinLock(&pClAf->Lock);
  437. ClearSapWithTapiLine(pClSap);
  438. Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
  439. if (Status != NDIS_STATUS_PENDING) {
  440. PxClDeregisterSapComplete(Status, pClSap);
  441. }
  442. NdisAcquireSpinLock(&pClAf->Lock);
  443. pe = pClAf->ClSapList.Flink;
  444. pClSap =
  445. CONTAINING_RECORD(pe, PX_CL_SAP, Linkage);
  446. } else {
  447. pe = pClSap->Linkage.Flink;
  448. pClSap =
  449. CONTAINING_RECORD(pe, PX_CL_SAP, Linkage);
  450. }
  451. }
  452. }
  453. //
  454. // deref for the ref applied when we opened this af
  455. // and put it on the adapter's list
  456. //
  457. DEREF_CL_AF_LOCKED(pClAf);
  458. NdisAcquireSpinLock(&pAdapter->Lock);
  459. }
  460. //
  461. // Do any clients have our AF open?
  462. //
  463. while (!IsListEmpty(&pAdapter->CmAfList)) {
  464. PPX_CM_AF pCmAf;
  465. PX_REQUEST ProxyRequest;
  466. PPX_REQUEST pProxyRequest = &ProxyRequest;
  467. ULONG Info = 0;
  468. PNDIS_REQUEST Request;
  469. pCmAf = (PPX_CM_AF)RemoveHeadList(&pAdapter->CmAfList);
  470. InsertTailList(&pAdapter->CmAfClosingList, &pCmAf->Linkage);
  471. NdisReleaseSpinLock(&pAdapter->Lock);
  472. NdisAcquireSpinLock(&pCmAf->Lock);
  473. pCmAf->State = PX_AF_CLOSING;
  474. REF_CM_AF(pCmAf);
  475. NdisReleaseSpinLock(&pCmAf->Lock);
  476. NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
  477. Request = &pProxyRequest->NdisRequest;
  478. Request->RequestType =
  479. NdisRequestSetInformation;
  480. Request->DATA.QUERY_INFORMATION.Oid =
  481. OID_CO_AF_CLOSE;
  482. Request->DATA.QUERY_INFORMATION.InformationBuffer =
  483. &Info;
  484. Request->DATA.QUERY_INFORMATION.InformationBufferLength =
  485. sizeof(ULONG);
  486. PxInitBlockStruc(&pProxyRequest->Block);
  487. Status = NdisCoRequest(pAdapter->CmBindingHandle,
  488. pCmAf->NdisAfHandle,
  489. NULL,
  490. NULL,
  491. Request);
  492. if (Status == NDIS_STATUS_PENDING) {
  493. Status = PxBlock(&pProxyRequest->Block);
  494. }
  495. DEREF_CM_AF(pCmAf);
  496. NdisAcquireSpinLock(&pAdapter->Lock);
  497. }
  498. NdisReleaseSpinLock(&pAdapter->Lock);
  499. if (IsClient) {
  500. PxInitBlockStruc(&pAdapter->ClCloseEvent);
  501. NdisCloseAdapter(&Status, pAdapter->ClBindingHandle);
  502. if (Status == NDIS_STATUS_PENDING) {
  503. PxBlock(&pAdapter->ClCloseEvent);
  504. }
  505. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxCoUnbindAdapter: CloseAdapter-Cl(%p)\n",
  506. pAdapter));
  507. } else {
  508. PxInitBlockStruc(&pAdapter->CmCloseEvent);
  509. NdisCloseAdapter(&Status, pAdapter->CmBindingHandle);
  510. if (Status == NDIS_STATUS_PENDING) {
  511. PxBlock(&pAdapter->CmCloseEvent);
  512. }
  513. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxCoUnbindAdapter: CloseAdapter-Cm(%p)\n",
  514. pAdapter));
  515. }
  516. DEREF_ADAPTER(pAdapter);
  517. *pStatus = NDIS_STATUS_SUCCESS;
  518. }
  519. VOID
  520. PxCoCloseAdaperComplete(
  521. NDIS_HANDLE BindingContext,
  522. NDIS_STATUS Status
  523. )
  524. /*++
  525. Routine Description
  526. Our CloseAdapter completion handler. We signal whoever closed the
  527. adapter.
  528. Arguments
  529. BindingContext - A pointer to a PX_ADAPTER structure.
  530. Status - Status of close attempt.
  531. Return Value:
  532. None
  533. --*/
  534. {
  535. PPX_ADAPTER pAdapter;
  536. BOOLEAN IsClient;
  537. AdapterFromBindContext(BindingContext, pAdapter, IsClient);
  538. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxCoCloseAdapterComp: Adapter %p\n", pAdapter));
  539. if (IsClient) {
  540. PxSignal(&pAdapter->ClCloseEvent, Status);
  541. } else {
  542. PxSignal(&pAdapter->CmCloseEvent, Status);
  543. }
  544. }
  545. VOID
  546. PxCoRequestComplete(
  547. IN NDIS_HANDLE BindingContext,
  548. IN PNDIS_REQUEST NdisRequest,
  549. IN NDIS_STATUS Status
  550. )
  551. {
  552. PPX_ADAPTER pAdapter;
  553. PPX_REQUEST pProxyRequest;
  554. BOOLEAN IsClient;
  555. AdapterFromBindContext(BindingContext, pAdapter, IsClient);
  556. PXDEBUGP(PXD_INFO, PXM_CO, ("PxCoRequestComplete: Adapter %p\n", pAdapter));
  557. pProxyRequest = CONTAINING_RECORD(NdisRequest, PX_REQUEST, NdisRequest);
  558. PxSignal(&pProxyRequest->Block, Status);
  559. }
  560. VOID
  561. PxCoNotifyAfRegistration(
  562. IN NDIS_HANDLE BindingContext,
  563. IN PCO_ADDRESS_FAMILY pFamily
  564. )
  565. /*++
  566. Routine Description:
  567. We get called here each time a call manager registers an address family.
  568. This is where we open the address family, and register a proxy version if we
  569. fancy it.
  570. Arguments:
  571. PxBindingContext - our pointer to an adapter
  572. pFamily - The AF that's been registered
  573. Return Value:
  574. None
  575. --*/
  576. {
  577. PPX_ADAPTER pAdapter;
  578. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  579. PPX_CL_AF pClAf;
  580. BOOLEAN IsClient;
  581. BOOLEAN CmAfRegistered;
  582. BOOLEAN Found;
  583. BOOLEAN RegisterInProgress = FALSE;
  584. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxNotifyAfRegistration\n"));
  585. //
  586. // First, check we're not being called because we registered ourselves...
  587. //
  588. if(pFamily->AddressFamily == CO_ADDRESS_FAMILY_TAPI) {
  589. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxNotifyAfRegistration: AF_TAPI registration -- do nothing\n"));
  590. return;
  591. }
  592. //
  593. // Get the adapter
  594. //
  595. AdapterFromBindContext(BindingContext, pAdapter, IsClient);
  596. if (!IsClient) {
  597. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxNotifyAfRegistration: Called for CM adapter -- do nothing\n"));
  598. return;
  599. }
  600. //
  601. // We need to keep the adapter around so place a ref on it!
  602. //
  603. NdisAcquireSpinLock(&pAdapter->Lock);
  604. REF_ADAPTER(pAdapter);
  605. NdisReleaseSpinLock(&pAdapter->Lock);
  606. //
  607. // Wait until we are finished with the binding!
  608. //
  609. PxBlock(&pAdapter->BindEvent);
  610. NdisAcquireSpinLock(&pAdapter->Lock);
  611. do {
  612. if ((pAdapter->State == PX_ADAPTER_CLOSING ||
  613. pAdapter->State == PX_ADAPTER_CLOSED)) {
  614. PXDEBUGP(PXD_FATAL, PXM_CO, ("PxNotifyAfRegistration: Adapter: %p state: %x is invalid\n",
  615. pAdapter, pAdapter->State));
  616. break;
  617. }
  618. //
  619. // See if this adapter already has this type of af registered
  620. //
  621. Found = FALSE;
  622. pClAf = (PPX_CL_AF)pAdapter->ClAfList.Flink;
  623. while ((PVOID)pClAf != (PVOID)&pAdapter->ClAfList) {
  624. if (pClAf->Af.AddressFamily == pFamily->AddressFamily) {
  625. Found = TRUE;
  626. break;
  627. }
  628. pClAf = (PPX_CL_AF)pClAf->Linkage.Flink;
  629. }
  630. if (Found) {
  631. PXDEBUGP(PXD_FATAL, PXM_CO, ("PxNotifyAfRegistration: Af already registered Adapter: %p, Af: %x\n",
  632. pAdapter, pClAf->Af));
  633. break;
  634. }
  635. pClAf =
  636. PxAllocateClAf(pFamily, pAdapter);
  637. if(pClAf == NULL) {
  638. Status = NDIS_STATUS_RESOURCES;
  639. PXDEBUGP(PXD_WARNING, PXM_CO, ("NotifyAfRegistration: failed to allocate a PX_CL_AF\n"));
  640. break;
  641. }
  642. //
  643. // Make sure that we don't let an Unbind thread invalidate our Binding
  644. // handle.
  645. //
  646. if (pAdapter->AfRegisteringCount == 0) {
  647. PxInitBlockStruc(&pAdapter->AfRegisterEvent);
  648. }
  649. pAdapter->AfRegisteringCount++;
  650. RegisterInProgress = TRUE;
  651. NdisReleaseSpinLock(&pAdapter->Lock);
  652. //
  653. // Open the address family
  654. //
  655. {
  656. NDIS_CLIENT_CHARACTERISTICS ClChars;
  657. PNDIS_CLIENT_CHARACTERISTICS pClChars = &ClChars;
  658. //
  659. // Do the client open on the address family
  660. //
  661. NdisZeroMemory (pClChars, sizeof(NDIS_CLIENT_CHARACTERISTICS));
  662. pClChars->MajorVersion = NDIS_MAJOR_VERSION;
  663. pClChars->MinorVersion = NDIS_MINOR_VERSION;
  664. pClChars->Reserved = 0;
  665. pClChars->ClCreateVcHandler = PxClCreateVc;
  666. pClChars->ClDeleteVcHandler = PxClDeleteVc;
  667. pClChars->ClOpenAfCompleteHandler = PxClOpenAfComplete;
  668. pClChars->ClCloseAfCompleteHandler = PxClCloseAfComplete;
  669. pClChars->ClRegisterSapCompleteHandler = PxClRegisterSapComplete;
  670. pClChars->ClDeregisterSapCompleteHandler = PxClDeregisterSapComplete;
  671. pClChars->ClMakeCallCompleteHandler = PxClMakeCallComplete;
  672. pClChars->ClModifyCallQoSCompleteHandler = PxClModifyCallQosComplete;
  673. pClChars->ClCloseCallCompleteHandler = PxClCloseCallComplete;
  674. pClChars->ClAddPartyCompleteHandler = PxClAddPartyComplete;
  675. pClChars->ClDropPartyCompleteHandler = PxClDropPartyComplete;
  676. pClChars->ClIncomingCallHandler = PxClIncomingCall;
  677. pClChars->ClIncomingCallQoSChangeHandler = PxClIncomingCallQosChange;
  678. pClChars->ClIncomingCloseCallHandler = PxClIncomingCloseCall;
  679. pClChars->ClIncomingDropPartyHandler = PxClIncomingDropParty;
  680. pClChars->ClCallConnectedHandler = PxClCallConnected;
  681. pClChars->ClRequestHandler = PxClRequest;
  682. pClChars->ClRequestCompleteHandler = PxClRequestComplete;
  683. PxInitBlockStruc(&pClAf->Block);
  684. Status = NdisClOpenAddressFamily(pAdapter->ClBindingHandle,
  685. pFamily,
  686. (NDIS_HANDLE)pClAf,
  687. pClChars,
  688. sizeof(NDIS_CLIENT_CHARACTERISTICS),
  689. &pClAf->NdisAfHandle);
  690. if(Status == NDIS_STATUS_PENDING) {
  691. Status = PxBlock(&pClAf->Block);
  692. }
  693. }
  694. NdisAcquireSpinLock(&pAdapter->Lock);
  695. if (Status != NDIS_STATUS_SUCCESS) {
  696. PXDEBUGP(PXD_WARNING, PXM_CO, ("NotifyAfRegistration: Error opening Af %x, Adapter %p, Error %x!!!\n",
  697. pFamily->AddressFamily, pAdapter, Status));
  698. PxFreeClAf(pClAf);
  699. break;
  700. }
  701. NdisAcquireSpinLock(&pClAf->Lock);
  702. pClAf->State = PX_AF_OPENED;
  703. NdisReleaseSpinLock(&pClAf->Lock);
  704. //
  705. // Have only need to register one instance of CO_ADDRESS_FAMILY_TAPI
  706. // for each adapter.
  707. //
  708. InsertTailList(&pAdapter->ClAfList, &pClAf->Linkage);
  709. if (pAdapter->Flags & PX_CMAF_REGISTERED) {
  710. CmAfRegistered = TRUE;
  711. } else {
  712. CmAfRegistered = FALSE;
  713. pAdapter->Flags |= PX_CMAF_REGISTERING;
  714. }
  715. REF_ADAPTER(pAdapter);
  716. NdisReleaseSpinLock(&pAdapter->Lock);
  717. if (!CmAfRegistered) {
  718. CO_ADDRESS_FAMILY PxFamily;
  719. NDIS_CALL_MANAGER_CHARACTERISTICS CmChars;
  720. PNDIS_CALL_MANAGER_CHARACTERISTICS pCmChars = &CmChars;
  721. //
  722. // Now register the Proxied address family. First, get the CM adapter handle.
  723. //
  724. NdisZeroMemory(pCmChars, sizeof(CmChars));
  725. pCmChars->MajorVersion = NDIS_MAJOR_VERSION;
  726. pCmChars->MinorVersion = NDIS_MINOR_VERSION;
  727. pCmChars->Reserved = 0;
  728. pCmChars->CmCreateVcHandler = PxCmCreateVc;
  729. pCmChars->CmDeleteVcHandler = PxCmDeleteVc;
  730. pCmChars->CmOpenAfHandler = PxCmOpenAf;
  731. pCmChars->CmCloseAfHandler = PxCmCloseAf;
  732. pCmChars->CmRegisterSapHandler = PxCmRegisterSap;
  733. pCmChars->CmDeregisterSapHandler = PxCmDeRegisterSap;
  734. pCmChars->CmMakeCallHandler = PxCmMakeCall;
  735. pCmChars->CmCloseCallHandler = PxCmCloseCall;
  736. pCmChars->CmIncomingCallCompleteHandler = PxCmIncomingCallComplete;
  737. pCmChars->CmAddPartyHandler = PxCmAddParty;
  738. pCmChars->CmDropPartyHandler = PxCmDropParty;
  739. pCmChars->CmActivateVcCompleteHandler = PxCmActivateVcComplete;
  740. pCmChars->CmDeactivateVcCompleteHandler = PxCmDeActivateVcComplete;
  741. pCmChars->CmModifyCallQoSHandler = PxCmModifyCallQos;
  742. pCmChars->CmRequestHandler = PxCmRequest;
  743. pCmChars->CmRequestCompleteHandler = PxCmRequestComplete;
  744. NdisMoveMemory(&PxFamily, pFamily, sizeof(PxFamily));
  745. PxFamily.AddressFamily = CO_ADDRESS_FAMILY_TAPI;
  746. PXDEBUGP(PXD_LOUD, PXM_CO, ("NotifyAfRegistration: NdisCmRegisterAddressFamily\n"));
  747. Status =
  748. NdisCmRegisterAddressFamily(pAdapter->CmBindingHandle,
  749. &PxFamily,
  750. pCmChars,
  751. sizeof(CmChars));
  752. NdisAcquireSpinLock(&pAdapter->Lock);
  753. pAdapter->Flags &= ~PX_CMAF_REGISTERING;
  754. if(Status != NDIS_STATUS_SUCCESS) {
  755. //
  756. // Close the CM af again
  757. //
  758. PXDEBUGP(PXD_FATAL, PXM_CO, ("NotifyAfRegistration: NdisCmRegisterAddressFamily on Bind %p bad sts = %x\n", pAdapter->CmBindingHandle, Status));
  759. RemoveEntryList(&pClAf->Linkage);
  760. InsertTailList(&pAdapter->ClAfClosingList, &pClAf->Linkage);
  761. NdisReleaseSpinLock(&pAdapter->Lock);
  762. NdisAcquireSpinLock(&pClAf->Lock);
  763. pClAf->State = PX_AF_CLOSING;
  764. NdisReleaseSpinLock(&pClAf->Lock);
  765. Status = NdisClCloseAddressFamily (pClAf->NdisAfHandle);
  766. if (Status != NDIS_STATUS_PENDING) {
  767. PxClCloseAfComplete(Status, pClAf);
  768. }
  769. NdisAcquireSpinLock(&pAdapter->Lock);
  770. break;
  771. } else {
  772. pAdapter->Flags |= PX_CMAF_REGISTERED;
  773. NdisReleaseSpinLock(&pAdapter->Lock);
  774. }
  775. }
  776. NdisAcquireSpinLock(&pClAf->Lock);
  777. REF_CL_AF(pClAf);
  778. NdisReleaseSpinLock(&pClAf->Lock);
  779. Status =
  780. AllocateTapiResources(pAdapter, pClAf);
  781. DEREF_CL_AF(pClAf);
  782. NdisAcquireSpinLock(&pAdapter->Lock);
  783. } while (FALSE);
  784. if (RegisterInProgress) {
  785. pAdapter->AfRegisteringCount--;
  786. if (pAdapter->AfRegisteringCount == 0) {
  787. PxSignal(&pAdapter->AfRegisterEvent, NDIS_STATUS_SUCCESS);
  788. }
  789. }
  790. DEREF_ADAPTER_LOCKED(pAdapter);
  791. }
  792. VOID
  793. PxCoUnloadProtocol(
  794. VOID
  795. )
  796. /*++
  797. Routine Description:
  798. Unload the entire protocol (CM and CL).
  799. Arguments:
  800. None
  801. Return Value:
  802. None
  803. --*/
  804. {
  805. NDIS_STATUS Status;
  806. NdisDeregisterProtocol(&Status, DeviceExtension->PxProtocolHandle);
  807. #if DBG
  808. NdisAcquireSpinLock(&(DeviceExtension->Lock));
  809. ASSERT(IsListEmpty(&DeviceExtension->AdapterList));
  810. NdisReleaseSpinLock(&DeviceExtension->Lock);
  811. #endif
  812. }
  813. NDIS_STATUS
  814. PxCoPnPEvent(
  815. IN NDIS_HANDLE BindingContext,
  816. IN PNET_PNP_EVENT pNetPnPEvent
  817. )
  818. {
  819. NDIS_STATUS Status;
  820. PPX_ADAPTER pAdapter=NULL;
  821. BOOLEAN IsClient;
  822. if (BindingContext != NULL) {
  823. AdapterFromBindContext(BindingContext, pAdapter, IsClient);
  824. }
  825. switch (pNetPnPEvent->NetEvent){
  826. case NetEventSetPower:
  827. Status = PxPnPSetPower(pAdapter, pNetPnPEvent);
  828. break;
  829. case NetEventQueryPower:
  830. Status = PxPnPQueryPower(pAdapter, pNetPnPEvent);
  831. break;
  832. case NetEventQueryRemoveDevice:
  833. Status = PxPnPQueryRemove(pAdapter, pNetPnPEvent);
  834. break;
  835. case NetEventCancelRemoveDevice:
  836. Status = PxPnPCancelRemove(pAdapter, pNetPnPEvent);
  837. break;
  838. case NetEventReconfigure:
  839. Status = PxPnPReconfigure(pAdapter, pNetPnPEvent);
  840. break;
  841. case NetEventBindList:
  842. Status = NDIS_STATUS_NOT_SUPPORTED;
  843. break;
  844. default:
  845. Status = NDIS_STATUS_NOT_SUPPORTED;
  846. break;
  847. }
  848. PXDEBUGP(PXD_INFO, PXM_CO, ("PnPEvent(CM): Event %d, returning %x\n",
  849. pNetPnPEvent->NetEvent, Status));
  850. return (Status);
  851. }
  852. NDIS_STATUS
  853. PxPnPSetPower(
  854. IN PPX_ADAPTER pAdapter,
  855. IN PNET_PNP_EVENT pNetPnPEvent
  856. )
  857. {
  858. PNET_DEVICE_POWER_STATE pPowerState;
  859. NDIS_STATUS Status;
  860. pPowerState = (PNET_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;
  861. switch (*pPowerState) {
  862. case NetDeviceStateD0:
  863. Status = NDIS_STATUS_SUCCESS;
  864. break;
  865. default:
  866. //
  867. // We can't suspend, so we ask NDIS to unbind us
  868. // by returning this status:
  869. //
  870. Status = NDIS_STATUS_NOT_SUPPORTED;
  871. break;
  872. }
  873. return (Status);
  874. }
  875. NDIS_STATUS
  876. PxPnPQueryPower(
  877. IN PPX_ADAPTER pAdapter,
  878. IN PNET_PNP_EVENT pNetPnPEvent
  879. )
  880. {
  881. return (NDIS_STATUS_SUCCESS);
  882. }
  883. NDIS_STATUS
  884. PxPnPQueryRemove(
  885. IN PPX_ADAPTER pAdapter,
  886. IN PNET_PNP_EVENT pNetPnPEvent
  887. )
  888. {
  889. return (NDIS_STATUS_SUCCESS);
  890. }
  891. NDIS_STATUS
  892. PxPnPCancelRemove(
  893. IN PPX_ADAPTER pAdapter,
  894. IN PNET_PNP_EVENT pNetPnPEvent
  895. )
  896. {
  897. return (NDIS_STATUS_SUCCESS);
  898. }
  899. NDIS_STATUS
  900. PxPnPReconfigure(
  901. IN PPX_ADAPTER pAdapter OPTIONAL,
  902. IN PNET_PNP_EVENT pNetPnPEvent
  903. )
  904. {
  905. return (NDIS_STATUS_NOT_SUPPORTED);
  906. }
  907. VOID
  908. PxCoSendComplete(
  909. IN NDIS_HANDLE ProtocolBindingContext,
  910. IN PNDIS_PACKET Packet,
  911. IN NDIS_STATUS Status
  912. )
  913. {
  914. PXDEBUGP(PXD_INFO, PXM_CO, ("PxCoSendComplete\n"));
  915. }
  916. VOID
  917. PxCoTransferDataComplete(
  918. IN NDIS_HANDLE ProtocolBindingContext,
  919. IN PNDIS_PACKET Packet,
  920. IN NDIS_STATUS Status,
  921. IN UINT BytesTransferred
  922. )
  923. {
  924. PXDEBUGP(PXD_INFO, PXM_CO, ("PxCoTransferDataComplete\n"));
  925. }
  926. VOID
  927. PxCoResetComplete(
  928. IN NDIS_HANDLE ProtocolBindingContext,
  929. IN NDIS_STATUS Status
  930. )
  931. {
  932. PXDEBUGP(PXD_INFO, PXM_CO, ("PxCoResetComplete\n"));
  933. }
  934. VOID
  935. PxCoStatusComplete(
  936. IN NDIS_HANDLE ProtocolBindingContext
  937. )
  938. {
  939. PXDEBUGP(PXD_INFO, PXM_CO, ("PxCoStatusComplete\n"));
  940. }
  941. VOID
  942. PxCoReceiveComplete(
  943. IN NDIS_HANDLE ProtocolBindingContext
  944. )
  945. {
  946. PXDEBUGP(PXD_INFO, PXM_CO, ("PxCoReceiveComplete\n"));
  947. }
  948. VOID
  949. PxCoStatus(
  950. IN NDIS_HANDLE ProtocolBindingContext,
  951. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  952. IN NDIS_STATUS GeneralStatus,
  953. IN PVOID StatusBuffer,
  954. IN UINT StatusBufferSize
  955. )
  956. {
  957. PPX_VC pVc = NULL;
  958. PXDEBUGP(PXD_INFO, PXM_CO,
  959. ("PxCoStatus : %p, Status %x\n",
  960. ProtocolBindingContext,GeneralStatus));
  961. GetVcFromCtx(ProtocolVcContext, &pVc);
  962. if (pVc == NULL) {
  963. return;
  964. }
  965. switch (GeneralStatus) {
  966. case NDIS_STATUS_TAPI_RECV_DIGIT:
  967. PxHandleReceivedDigit(pVc,
  968. StatusBuffer,
  969. StatusBufferSize);
  970. break;
  971. case NDIS_STATUS_WAN_CO_LINKPARAMS:
  972. PxHandleWanLinkParams(pVc,
  973. StatusBuffer,
  974. StatusBufferSize);
  975. break;
  976. default:
  977. break;
  978. }
  979. DEREF_VC(pVc);
  980. }
  981. UINT
  982. PxCoReceivePacket(
  983. IN NDIS_HANDLE ProtocolBindingContext,
  984. IN NDIS_HANDLE ProtocolVcContext,
  985. IN PNDIS_PACKET pNdisPacket
  986. )
  987. {
  988. PXDEBUGP(PXD_INFO, PXM_CO, ("CoReceivePacket\n"));
  989. NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_SUCCESS);
  990. return 0;
  991. }
  992. ULONG
  993. PxGetMillisecondTickCount()
  994. {
  995. LARGE_INTEGER TickCount, Milliseconds;
  996. ULONG TimeIncrement;
  997. //
  998. // Return the current "tick count" (number of milliseconds since Windows started).
  999. // TAPI wants this in its DTMF notification messages. We have to do a little math here because
  1000. // the kernel query tick count function returns the number of timer ticks, which is some
  1001. // multiple of 100ns.
  1002. //
  1003. KeQueryTickCount(&TickCount);
  1004. TimeIncrement = KeQueryTimeIncrement();
  1005. Milliseconds.QuadPart = (TickCount.QuadPart / 10000) * TimeIncrement;
  1006. //
  1007. // This might seem a bit sketchy but TAPI only gives us a 32-bit wide place to store the tick
  1008. // count. According to the SDK, TAPI apps are supposed to be aware that this will roll over every
  1009. // 49.7 days. (...it's amusing to think of TAPI staying up for 49.7 days, but I digress...)
  1010. //
  1011. return (Milliseconds.LowPart);
  1012. }
  1013. // PxTerminateDigitDetection
  1014. //
  1015. // Must be called with the VC lock held.
  1016. VOID
  1017. PxTerminateDigitDetection(
  1018. IN PPX_VC pVc,
  1019. IN PNDISTAPI_REQUEST pNdisTapiRequest,
  1020. IN ULONG ulReason
  1021. )
  1022. {
  1023. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits;
  1024. PIRP Irp;
  1025. PWCHAR pDigitsBuffer;
  1026. NDIS_STATUS Status;
  1027. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxTerminateDigitDetection: Enter\n"));
  1028. pNdisTapiGatherDigits =
  1029. (PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
  1030. Irp = pNdisTapiRequest->Irp;
  1031. pNdisTapiGatherDigits->ulTickCount = PxGetMillisecondTickCount();
  1032. pNdisTapiGatherDigits->ulTerminationReason = ulReason;
  1033. //
  1034. // Put the null character at the end of the buffer, and send it on it's way.
  1035. //
  1036. pDigitsBuffer =
  1037. (PWCHAR) (((PUCHAR)pNdisTapiGatherDigits) + pNdisTapiGatherDigits->ulDigitsBufferOffset);
  1038. pDigitsBuffer[pNdisTapiGatherDigits->ulNumDigitsRead] =
  1039. UNICODE_NULL;
  1040. Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
  1041. Irp->IoStatus.Information =
  1042. sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
  1043. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1044. //
  1045. // Note: we call release here even though we didn't acquire in this function.
  1046. // This is OK since this function MUST be called with the lock held.
  1047. //
  1048. NdisReleaseSpinLock(&pVc->Lock);
  1049. Status = PxStopDigitReporting(pVc);
  1050. NdisAcquireSpinLock(&pVc->Lock); // See comment above.
  1051. // FIXME: If this failed (i.e. Status is some error value,
  1052. // there's not much we can do about it here).
  1053. if (Status != NDIS_STATUS_SUCCESS) {
  1054. PXDEBUGP(PXD_ERROR, PXM_CO,
  1055. ("PxTerminateDigitDetection: PxStopDigitReporting returned Status 0x%x\n",
  1056. Status));
  1057. ASSERT(FALSE);
  1058. }
  1059. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxTerminateDigitDetection: Exit\n"));
  1060. }
  1061. VOID
  1062. PxDigitTimerRoutine(
  1063. IN PVOID SystemSpecific1,
  1064. IN PVOID FunctionContext,
  1065. IN PVOID SystemSpecific2,
  1066. IN PVOID SystemSpecific3
  1067. )
  1068. {
  1069. PPX_VC pVc = (PPX_VC) FunctionContext;
  1070. PNDISTAPI_REQUEST pNdisTapiRequest;
  1071. PIRP Irp;
  1072. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits;
  1073. ULONG ulReason;
  1074. NdisAcquireSpinLock(&pVc->Lock);
  1075. do {
  1076. if (pVc->PendingGatherDigits == NULL) {
  1077. //
  1078. // The request either completed, or a digit is being processed right now, so this timeout is
  1079. // meaningless.
  1080. //
  1081. break;
  1082. }
  1083. pNdisTapiRequest = pVc->PendingGatherDigits;
  1084. Irp = pNdisTapiRequest->Irp;
  1085. if (!IoSetCancelRoutine(Irp, NULL))
  1086. {
  1087. //
  1088. // The cancel routine is running. Let it handle the IRP.
  1089. //
  1090. break;
  1091. }
  1092. pVc->PendingGatherDigits = NULL;
  1093. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  1094. pNdisTapiGatherDigits =
  1095. (PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
  1096. if (pNdisTapiGatherDigits->ulNumDigitsRead == 0) {
  1097. //
  1098. // We timed out before detecting the first digit.
  1099. //
  1100. ulReason = LINEGATHERTERM_FIRSTTIMEOUT;
  1101. } else {
  1102. ulReason = LINEGATHERTERM_INTERTIMEOUT;
  1103. }
  1104. PxTerminateDigitDetection(pVc, pNdisTapiRequest, ulReason);
  1105. } while (FALSE);
  1106. NdisReleaseSpinLock(&pVc->Lock);
  1107. DEREF_VC(pVc);
  1108. }
  1109. // ++ DTMFDigitToOrdinal
  1110. //
  1111. // Turn a DTMF digit into a number between 0 and 15. The digits are assigned
  1112. // numbers in the following order: '0' - '9', 'A' - 'D', '*', '#'.
  1113. //
  1114. // This is horribly ugly now, but we'll optimize later.
  1115. //
  1116. // Arguments:
  1117. // wcDigit - The digit, expressed as a UNICODE character.
  1118. //
  1119. // Return value:
  1120. // A number between 0 and 15, or 16 if the digit passed in was not a valid
  1121. // DTMF digit.
  1122. //
  1123. ULONG
  1124. DTMFDigitToOrdinal(
  1125. WCHAR wcDigit
  1126. )
  1127. {
  1128. ULONG ulOrdinal;
  1129. switch (wcDigit) {
  1130. case L'0':
  1131. ulOrdinal = 0;
  1132. break;
  1133. case L'1':
  1134. ulOrdinal = 1;
  1135. break;
  1136. case L'2':
  1137. ulOrdinal = 2;
  1138. break;
  1139. case L'3':
  1140. ulOrdinal = 3;
  1141. break;
  1142. case L'4':
  1143. ulOrdinal = 4;
  1144. break;
  1145. case L'5':
  1146. ulOrdinal = 5;
  1147. break;
  1148. case L'6':
  1149. ulOrdinal = 6;
  1150. break;
  1151. case L'7':
  1152. ulOrdinal = 7;
  1153. break;
  1154. case L'8':
  1155. ulOrdinal = 8;
  1156. break;
  1157. case L'9':
  1158. ulOrdinal = 9;
  1159. break;
  1160. case L'A':
  1161. ulOrdinal = 10;
  1162. break;
  1163. case L'B':
  1164. ulOrdinal = 11;
  1165. break;
  1166. case L'C':
  1167. ulOrdinal = 12;
  1168. break;
  1169. case L'D':
  1170. ulOrdinal = 13;
  1171. break;
  1172. case L'*':
  1173. ulOrdinal = 14;
  1174. break;
  1175. case L'#':
  1176. ulOrdinal = 15;
  1177. break;
  1178. default:
  1179. ulOrdinal = 16;
  1180. break;
  1181. };
  1182. return ulOrdinal;
  1183. }
  1184. NDIS_STATUS
  1185. PxStopDigitReporting(
  1186. PPX_VC pVc
  1187. )
  1188. {
  1189. PX_REQUEST ProxyRequest;
  1190. PNDIS_REQUEST NdisRequest;
  1191. ULONG Unused = 0;
  1192. NDIS_STATUS Status;
  1193. //
  1194. // Fill out our request structure to tell the miniport to stop reporting
  1195. // digits.
  1196. //
  1197. NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
  1198. PxInitBlockStruc(&ProxyRequest.Block);
  1199. NdisRequest = &ProxyRequest.NdisRequest;
  1200. NdisRequest->RequestType = NdisRequestSetInformation;
  1201. NdisRequest->DATA.SET_INFORMATION.Oid = OID_CO_TAPI_DONT_REPORT_DIGITS;
  1202. NdisRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&Unused;
  1203. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(Unused);
  1204. Status = NdisCoRequest(pVc->Adapter->ClBindingHandle,
  1205. pVc->ClAf->NdisAfHandle,
  1206. pVc->ClVcHandle,
  1207. NULL,
  1208. NdisRequest);
  1209. if (Status == NDIS_STATUS_PENDING) {
  1210. Status = PxBlock(&ProxyRequest.Block);
  1211. }
  1212. return Status;
  1213. }
  1214. VOID
  1215. PxHandleReceivedDigit(
  1216. IN PPX_VC pVc,
  1217. IN PVOID Buffer,
  1218. IN UINT BufferSize
  1219. )
  1220. {
  1221. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits;
  1222. PWCHAR pDigitsBuffer;
  1223. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxHandleReceiveDigit: Enter\n"));
  1224. do {
  1225. PLIST_ENTRY Entry;
  1226. PIRP Irp;
  1227. PNDISTAPI_REQUEST pNdisTapiRequest;
  1228. ULONG ulDigitOrdinal;
  1229. BOOLEAN bTimerCancelled = FALSE;
  1230. //
  1231. // We need at least one WCHAR in the buffer.
  1232. //
  1233. if (BufferSize < sizeof(WCHAR)) {
  1234. //
  1235. // No useful data, get out
  1236. //
  1237. break;
  1238. }
  1239. NdisAcquireSpinLock(&pVc->Lock);
  1240. if (pVc->ulMonitorDigitsModes != 0) {
  1241. NDIS_TAPI_EVENT Event;
  1242. PPX_TAPI_LINE pTapiLine;
  1243. //
  1244. // We're monitoring (not gathering) digits, so send up a message right away.
  1245. //
  1246. pTapiLine = pVc->TapiLine;
  1247. Event.htLine = pTapiLine->htLine;
  1248. Event.htCall = pVc->htCall;
  1249. Event.ulMsg = LINE_MONITORDIGITS;
  1250. Event.ulParam1 = (ULONG_PTR) (* ((PWCHAR)Buffer));
  1251. Event.ulParam2 = (ULONG_PTR) (pVc->ulMonitorDigitsModes); // ToDo - There could be > 1 mode here - have to get this from the driver.
  1252. Event.ulParam3 = (ULONG_PTR) (PxGetMillisecondTickCount());
  1253. NdisReleaseSpinLock(&pVc->Lock);
  1254. PxIndicateStatus((PVOID) &Event, sizeof(NDIS_TAPI_EVENT));
  1255. break;
  1256. }
  1257. if (pVc->PendingGatherDigits == NULL) {
  1258. //
  1259. // No Irp to complete, get out
  1260. //
  1261. NdisReleaseSpinLock(&pVc->Lock);
  1262. break;
  1263. }
  1264. NdisCancelTimer(&pVc->DigitTimer, &bTimerCancelled); // deref of VC is at the end - makes locking code a bit cleaner.
  1265. pNdisTapiRequest = pVc->PendingGatherDigits;
  1266. Irp = pNdisTapiRequest->Irp;
  1267. if (!IoSetCancelRoutine(Irp, NULL))
  1268. {
  1269. //
  1270. // The cancel routine is running. Let it handle the IRP.
  1271. //
  1272. NdisReleaseSpinLock(&pVc->Lock);
  1273. break;
  1274. }
  1275. pVc->PendingGatherDigits = NULL;
  1276. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  1277. pNdisTapiGatherDigits =
  1278. (PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
  1279. //
  1280. // Store the current digit, and increment the count.
  1281. //
  1282. pDigitsBuffer =
  1283. (PWCHAR) (((PUCHAR)pNdisTapiGatherDigits) + pNdisTapiGatherDigits->ulDigitsBufferOffset);
  1284. pDigitsBuffer[pNdisTapiGatherDigits->ulNumDigitsRead] =
  1285. *((PWCHAR)Buffer);
  1286. pNdisTapiGatherDigits->ulNumDigitsRead++;
  1287. //
  1288. // Check if we read a termination digit.
  1289. //
  1290. ulDigitOrdinal = DTMFDigitToOrdinal(*((PWCHAR)Buffer));
  1291. if (Irp->Cancel) {
  1292. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
  1293. } else if (pNdisTapiGatherDigits->ulTerminationDigitsMask & (1 << ulDigitOrdinal)) {
  1294. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_TERMDIGIT);
  1295. } else if (pNdisTapiGatherDigits->ulNumDigitsRead == pNdisTapiGatherDigits->ulNumDigitsNeeded) {
  1296. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_BUFFERFULL);
  1297. } else {
  1298. pVc->PendingGatherDigits = pNdisTapiRequest;
  1299. if (pNdisTapiGatherDigits->ulInterDigitTimeout) {
  1300. REF_VC(pVc);
  1301. NdisSetTimer(&pVc->DigitTimer, pNdisTapiGatherDigits->ulInterDigitTimeout);
  1302. }
  1303. IoSetCancelRoutine(Irp, PxCancelSetQuery);
  1304. }
  1305. NdisReleaseSpinLock(&pVc->Lock);
  1306. if (bTimerCancelled) {
  1307. //
  1308. // Do this only if the timer was actually cancelled. If it wasn't, then
  1309. // either it wasn't set and the VC wouldn't have been ref'd in the first
  1310. // place, or it fired, in which case the timer routine would have deref'd
  1311. // it already.
  1312. //
  1313. DEREF_VC(pVc);
  1314. }
  1315. } while (FALSE);
  1316. PXDEBUGP(PXD_LOUD, PXM_CO, ("PxHandleReceiveDigit: Exit\n"));
  1317. }
  1318. VOID
  1319. PxHandleWanLinkParams(
  1320. IN PPX_VC pVc,
  1321. IN PVOID Buffer,
  1322. IN UINT BufferSize
  1323. )
  1324. {
  1325. }