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.

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