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.

5204 lines
134 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. pxtapi.c
  5. Abstract:
  6. The module contains the TAPI-specific code for the NDIS Proxy.
  7. Author:
  8. Richard Machin (RMachin)
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. RMachin 01-08-97 created (after Dan Knudson's NdisTapi)
  13. TonyBe 02-21-99 re-work/re-write
  14. Notes:
  15. --*/
  16. #include <precomp.h>
  17. #include <stdio.h>
  18. #define MODULE_NUMBER MODULE_TAPI
  19. #define _FILENUMBER 'IPAT'
  20. ULONG
  21. GetLineEvents(
  22. PCHAR EventBuffer,
  23. ULONG BufferSize
  24. )
  25. /*++
  26. Routine Description:
  27. Gets event data out of our global event queue and writes it to the buffer. Data is put into the queue
  28. by PxIndicateStatus (above).
  29. Arguments:
  30. EventBuffer pointer to a buffer of size BufferSize
  31. BufferSize size of event buffer (expected to be 1024)
  32. Return Value:
  33. Note:
  34. Assumes TspEventList.Lock held by caller.
  35. --*/
  36. {
  37. ULONG BytesLeft;
  38. ULONG BytesMoved = 0;
  39. BytesLeft = BufferSize;
  40. while (!(IsListEmpty(&TspEventList.List))) {
  41. PPROVIDER_EVENT ProviderEvent;
  42. if (BytesLeft < sizeof(NDIS_TAPI_EVENT)) {
  43. break;
  44. }
  45. ProviderEvent = (PPROVIDER_EVENT)
  46. RemoveHeadList(&TspEventList.List);
  47. TspEventList.Count--;
  48. RtlMoveMemory(EventBuffer + BytesMoved,
  49. (PUCHAR)&ProviderEvent->Event,
  50. sizeof(NDIS_TAPI_EVENT));
  51. BytesMoved += sizeof(NDIS_TAPI_EVENT);
  52. BytesLeft -= sizeof(NDIS_TAPI_EVENT);
  53. ExFreeToNPagedLookasideList(&ProviderEventLookaside,
  54. ProviderEvent);
  55. }
  56. return (BytesMoved);
  57. }
  58. NDIS_STATUS
  59. PxTapiMakeCall(
  60. IN PNDISTAPI_REQUEST pNdisTapiRequest
  61. )
  62. /*++
  63. Routine Description:
  64. TSPI_lineMakeCall handler.
  65. Arguments:
  66. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  67. Return Value:
  68. --*/
  69. {
  70. PNDIS_TAPI_MAKE_CALL TapiBuffer =
  71. (PNDIS_TAPI_MAKE_CALL)(pNdisTapiRequest->Data);
  72. LINE_CALL_PARAMS* pTapiCallParams =
  73. (LINE_CALL_PARAMS*)(&TapiBuffer->LineCallParams);
  74. PPX_TAPI_LINE TapiLine;
  75. PPX_TAPI_ADDR TapiAddr;
  76. PPX_VC pVc = NULL;
  77. PPX_CL_AF pClAf;
  78. PCO_CALL_PARAMETERS pNdisCallParams = 0;
  79. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  80. ULONG targetDeviceID = 0;
  81. LPCWSTR lpcwszTemp;
  82. PPX_ADAPTER pAdapter;
  83. PPX_TAPI_PROVIDER TapiProvider;
  84. lpcwszTemp = (LPWSTR)
  85. (((UCHAR *) TapiBuffer) + TapiBuffer->ulDestAddressOffset);
  86. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  87. ("TapiMakeCall: DialAddress in Tapi buffer %x = %ls\n",lpcwszTemp, lpcwszTemp));
  88. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  89. PXDEBUGP (PXD_WARNING, PXM_TAPI,
  90. ("PxTapiMakeCall: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
  91. return (NDISTAPIERR_BADDEVICEID);
  92. }
  93. do {
  94. NdisAcquireSpinLock(&TapiLine->Lock);
  95. //
  96. // Is this line in service? (does it have an valid af?)
  97. //
  98. if (!(TapiLine->DevStatus->ulDevStatusFlags &
  99. LINEDEVSTATUSFLAGS_INSERVICE)) {
  100. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  101. ("PxTapiMakeCall: Line not in service!\n"));
  102. NdisReleaseSpinLock(&TapiLine->Lock);
  103. Status = NDISTAPIERR_DEVICEOFFLINE;
  104. break;
  105. }
  106. PXDEBUGP (PXD_TAPI, PXM_TAPI,
  107. ("PxTapiMakeCall: got device x%x from ID %d\n", TapiLine, TapiBuffer->hdLine));
  108. if (pTapiCallParams->ulAddressMode == LINEADDRESSMODE_ADDRESSID) {
  109. //
  110. // Get the specificed address from the address id
  111. //
  112. if (!IsAddressValid(TapiLine, pTapiCallParams->ulAddressID, &TapiAddr)) {
  113. Status = NDISTAPIERR_BADDEVICEID;
  114. NdisReleaseSpinLock(&TapiLine->Lock);
  115. break;
  116. }
  117. } else {
  118. //
  119. // Get the first available address
  120. //
  121. TapiAddr =
  122. GetAvailAddrFromLine(TapiLine);
  123. if (TapiAddr == NULL) {
  124. Status = NDISTAPIERR_BADDEVICEID;
  125. NdisReleaseSpinLock(&TapiLine->Lock);
  126. break;
  127. }
  128. }
  129. TapiProvider = TapiLine->TapiProvider;
  130. pAdapter = TapiProvider->Adapter;
  131. pClAf = TapiLine->ClAf;
  132. NdisReleaseSpinLock(&TapiLine->Lock);
  133. NdisAcquireSpinLock(&pClAf->Lock);
  134. //
  135. // Allocate a Vc block. This will create the block
  136. // with refcount = 1.
  137. //
  138. pVc = PxAllocateVc(pClAf);
  139. if (pVc == NULL) {
  140. PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiMakeCall: failed to allocate a vc\n"));
  141. NdisReleaseSpinLock(&pClAf->Lock);
  142. Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
  143. break;
  144. }
  145. NdisReleaseSpinLock(&pClAf->Lock);
  146. Status =
  147. AllocateTapiCallInfo(pVc, NULL);
  148. if (Status != NDIS_STATUS_SUCCESS) {
  149. PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiMakeCall: Error allocating TapiCallInfo!\n"));
  150. PxFreeVc(pVc);
  151. Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
  152. break;
  153. }
  154. pVc->TapiLine = TapiLine;
  155. pVc->TapiAddr = TapiAddr;
  156. InterlockedIncrement((PLONG)&TapiAddr->CallCount);
  157. InterlockedIncrement((PLONG)&TapiLine->DevStatus->ulNumActiveCalls);
  158. pVc->htCall = TapiBuffer->htCall;
  159. pVc->CallInfo->ulLineDeviceID = TapiLine->CmLineID;
  160. pVc->CallInfo->ulAddressID = TapiAddr->AddrId;
  161. pVc->CallInfo->ulOrigin = LINECALLORIGIN_OUTBOUND;
  162. //
  163. // Set up intended bearer and media mode
  164. //
  165. pVc->CallInfo->ulBearerMode =
  166. pTapiCallParams->ulBearerMode;
  167. pVc->CallInfo->ulMediaMode =
  168. pTapiCallParams->ulMediaMode;
  169. if (pTapiCallParams->ulMaxRate == 0) {
  170. pVc->CallInfo->ulRate =
  171. TapiLine->DevCaps->ulMaxRate;
  172. } else {
  173. pVc->CallInfo->ulRate =
  174. pTapiCallParams->ulMaxRate;
  175. }
  176. if (!InsertVcInTable(pVc)) {
  177. PXDEBUGP (PXD_WARNING, PXM_TAPI,
  178. ("PxTapiMakeCall: failed to insert in vc table\n"));
  179. PxFreeVc(pVc);
  180. Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
  181. break;
  182. }
  183. //
  184. // Our call handle is an index into the call table
  185. //
  186. TapiBuffer->hdCall = (HDRV_CALL)pVc->hdCall;
  187. Status = NdisCoCreateVc(pAdapter->ClBindingHandle,
  188. pClAf->NdisAfHandle,
  189. (NDIS_HANDLE)pVc->hdCall,
  190. &pVc->ClVcHandle);
  191. if (Status != NDIS_STATUS_SUCCESS) {
  192. RemoveVcFromTable(pVc);
  193. PxFreeVc(pVc);
  194. Status = NDIS_STATUS_TAPI_CALLUNAVAIL;
  195. break;
  196. }
  197. //
  198. // Move (AF-specific) call parameters into NdisCallParams structure
  199. //
  200. Status =
  201. (*pClAf->AfGetNdisCallParams)(pVc,
  202. TapiLine->CmLineID,
  203. TapiAddr->AddrId,
  204. CO_TAPI_FLAG_OUTGOING_CALL,
  205. TapiBuffer,
  206. &pNdisCallParams);
  207. if (Status != NDIS_STATUS_SUCCESS) {
  208. PXDEBUGP (PXD_WARNING, PXM_TAPI,
  209. ("PxTapiMakeCall: failed to move call params: Status %x\n", Status));
  210. NdisCoDeleteVc(pVc->ClVcHandle);
  211. RemoveVcFromTable(pVc);
  212. PxFreeVc(pVc);
  213. Status = NDIS_STATUS_TAPI_INVALCALLPARAMS;
  214. break;
  215. }
  216. // Store Call Params for when lineGetID dispatches an incoming call...
  217. //
  218. NdisAcquireSpinLock(&pVc->Lock);
  219. pVc->pCallParameters = pNdisCallParams;
  220. pVc->PrevState = pVc->State;
  221. pVc->State = PX_VC_PROCEEDING;
  222. pVc->Flags |= PX_VC_OWNER;
  223. //
  224. // Ref applied ndis part of the make call.
  225. // This ref is removed in PxClCloseCallComplete or
  226. // PxClMakeCallComplete in the case of a make call
  227. // failure.
  228. //
  229. REF_VC(pVc);
  230. //
  231. // Indicate call state change to TAPI
  232. //
  233. SendTapiCallState(pVc,
  234. LINECALLSTATE_PROCEEDING,
  235. 0,
  236. pVc->CallInfo->ulMediaMode);
  237. NdisReleaseSpinLock(&pVc->Lock);
  238. Status =
  239. NdisClMakeCall(pVc->ClVcHandle,
  240. pVc->pCallParameters,
  241. NULL,
  242. NULL);
  243. if (Status != NDIS_STATUS_PENDING) {
  244. PxClMakeCallComplete(Status,
  245. (NDIS_HANDLE)pVc->hdCall,
  246. NULL,
  247. pVc->pCallParameters);
  248. }
  249. Status = NDIS_STATUS_SUCCESS;
  250. } // end of do loop
  251. while (FALSE);
  252. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiMakeCall: exit Status %x\n", Status));
  253. DEREF_TAPILINE(TapiLine);
  254. return Status;
  255. }
  256. NDIS_STATUS
  257. PxTapiGetDevCaps(
  258. IN PNDISTAPI_REQUEST pNdisTapiRequest
  259. )
  260. /*++
  261. Routine Description:
  262. Stick the appropriate device info into the request buffer.
  263. Arguments:
  264. Request -- the request that arrived in an IRP system buffer
  265. Return Value:
  266. --*/
  267. {
  268. PPX_TAPI_LINE TapiLine = NULL;
  269. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  270. PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps =
  271. (PNDIS_TAPI_GET_DEV_CAPS) pNdisTapiRequest->Data;
  272. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevCaps: enter\n"));
  273. if (!IsTapiDeviceValid(pNdisTapiGetDevCaps->ulDeviceID, &TapiLine)) {
  274. PXDEBUGP (PXD_WARNING, PXM_TAPI,
  275. ( "PxTapiGetDevCaps: NDISTAPIERR_BADDEVICEID: line = %x\n",
  276. pNdisTapiGetDevCaps->ulDeviceID));
  277. return(NDISTAPIERR_BADDEVICEID);
  278. }
  279. NdisAcquireSpinLock(&TapiLine->Lock);
  280. do {
  281. ULONG SizeDevCaps;
  282. ULONG DevClassesSize = 0;
  283. USHORT DevClassesList[512];
  284. WCHAR LineName[128];
  285. ULONG LineNameSize;
  286. WCHAR ProviderInfo[128];
  287. ULONG ProviderInfoSize;
  288. PLINE_DEV_CAPS ldc;
  289. PPX_ADAPTER ClAdapter;
  290. ULONG SizeToMove;
  291. LONG SizeLeft;
  292. PUCHAR dst;
  293. ULONG TotalSize;
  294. //
  295. // Synchronously get dev caps for this device
  296. //
  297. ClAdapter = TapiLine->TapiProvider->Adapter;
  298. ldc = TapiLine->DevCaps;
  299. SizeDevCaps = ldc->ulUsedSize;
  300. //
  301. // Add some space for our providerinfo if needed
  302. //
  303. if (ldc->ulProviderInfoSize == 0) {
  304. NdisZeroMemory(ProviderInfo, sizeof(ProviderInfo));
  305. ProviderInfoSize = wcslen(L"NDPROXY") * sizeof(WCHAR);
  306. NdisMoveMemory((PUCHAR)ProviderInfo,
  307. L"NDPROXY",
  308. ProviderInfoSize);
  309. //
  310. // For NULL termination
  311. //
  312. ProviderInfoSize += sizeof(UNICODE_NULL);
  313. SizeDevCaps += ProviderInfoSize;
  314. }
  315. //
  316. // Add some space for our linename if needed
  317. //
  318. if ((ldc->ulLineNameSize == 0) &&
  319. (ClAdapter != NULL) &&
  320. (ClAdapter->MediaNameLength != 0)) {
  321. PUCHAR dst;
  322. NdisZeroMemory(LineName, sizeof(LineName));
  323. dst = (PUCHAR)LineName;
  324. NdisMoveMemory(dst,
  325. (PUCHAR)(ClAdapter->MediaName),
  326. ClAdapter->MediaNameLength);
  327. (ULONG_PTR)dst += ClAdapter->MediaNameLength;
  328. //
  329. // ToDo! Shoud get the name of the adapter
  330. // and insert here!
  331. //
  332. NdisMoveMemory(dst,
  333. L" - Line",
  334. wcslen(L" - Line") * sizeof(WCHAR));
  335. (ULONG_PTR)dst +=
  336. wcslen(L" - Line") * sizeof(WCHAR);
  337. (VOID)
  338. IntegerToWChar(TapiLine->CmLineID,
  339. -4,
  340. (WCHAR *)dst);
  341. (ULONG_PTR)dst += 4 * sizeof(WCHAR);
  342. LineNameSize = (ULONG)((ULONG_PTR)dst - (ULONG_PTR)LineName);
  343. //
  344. // For NULL termination
  345. //
  346. LineNameSize += sizeof(UNICODE_NULL);
  347. SizeDevCaps += LineNameSize;
  348. }
  349. //
  350. // Add some space for our device classes
  351. //
  352. DevClassesSize = sizeof(DevClassesList);
  353. NdisZeroMemory((PUCHAR)DevClassesList,
  354. sizeof(DevClassesList));
  355. if (ClAdapter != NULL) {
  356. GetAllDevClasses(ClAdapter,
  357. DevClassesList,
  358. &DevClassesSize);
  359. }
  360. SizeDevCaps += DevClassesSize;
  361. ldc = &pNdisTapiGetDevCaps->LineDevCaps;
  362. SizeToMove = (TapiLine->DevCaps->ulUsedSize > ldc->ulTotalSize) ?
  363. ldc->ulTotalSize : TapiLine->DevCaps->ulUsedSize;
  364. SizeLeft = ldc->ulTotalSize - SizeToMove;
  365. //
  366. // Save the total size
  367. //
  368. TotalSize = ldc->ulTotalSize;
  369. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  370. ("PxTapiGetDevCaps: got device %x from ID %d: moving %d bytes\n",
  371. TapiLine,
  372. pNdisTapiGetDevCaps->ulDeviceID,
  373. SizeToMove));
  374. NdisMoveMemory((PUCHAR)ldc,
  375. (PUCHAR)TapiLine->DevCaps,
  376. SizeToMove);
  377. ldc->ulNeededSize = SizeDevCaps;
  378. ldc->ulTotalSize = TotalSize;
  379. ldc->ulUsedSize = SizeToMove;
  380. if (SizeLeft > 0) {
  381. //
  382. // If there is no provider info fill our proxy info
  383. //
  384. if (ldc->ulProviderInfoSize == 0) {
  385. dst = (PUCHAR)ldc + ldc->ulUsedSize;
  386. SizeToMove = (SizeLeft > (LONG)ProviderInfoSize) ?
  387. ProviderInfoSize : SizeLeft;
  388. NdisMoveMemory(dst,
  389. (PUCHAR)ProviderInfo,
  390. SizeToMove);
  391. ldc->ulProviderInfoSize = SizeToMove;
  392. ldc->ulProviderInfoOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
  393. ldc->ulUsedSize += SizeToMove;
  394. SizeLeft -= SizeToMove;
  395. }
  396. }
  397. if (SizeLeft > 0) {
  398. //
  399. // If these is no line name fill in our line name
  400. //
  401. if (ldc->ulLineNameSize == 0 &&
  402. ClAdapter != NULL &&
  403. ClAdapter->MediaNameLength != 0) {
  404. dst = (PUCHAR)ldc + ldc->ulUsedSize;
  405. SizeToMove = (SizeLeft > (LONG)LineNameSize) ?
  406. LineNameSize : SizeLeft;
  407. NdisMoveMemory(dst,
  408. (PUCHAR)LineName,
  409. SizeToMove);
  410. ldc->ulLineNameSize = SizeToMove;
  411. ldc->ulLineNameOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
  412. ldc->ulUsedSize += SizeToMove;
  413. SizeLeft -= SizeToMove;
  414. }
  415. }
  416. if (SizeLeft > 0) {
  417. //
  418. // Add the devclasses to the end
  419. //
  420. if (DevClassesSize > 0) {
  421. dst = (PUCHAR)ldc + ldc->ulUsedSize;
  422. SizeToMove = (SizeLeft > (LONG)DevClassesSize) ?
  423. DevClassesSize : SizeLeft;
  424. NdisMoveMemory(dst,
  425. DevClassesList,
  426. SizeToMove);
  427. ldc->ulDeviceClassesSize = SizeToMove;
  428. ldc->ulDeviceClassesOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
  429. ldc->ulUsedSize += SizeToMove;
  430. SizeLeft -= SizeToMove;
  431. }
  432. }
  433. } while (FALSE);
  434. DEREF_TAPILINE_LOCKED(TapiLine);
  435. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevCaps: exit: used=%d, needed=%d, total=%d\n",
  436. pNdisTapiGetDevCaps->LineDevCaps.ulUsedSize,
  437. pNdisTapiGetDevCaps->LineDevCaps.ulNeededSize,
  438. pNdisTapiGetDevCaps->LineDevCaps.ulTotalSize));
  439. return (Status);
  440. }
  441. NDIS_STATUS
  442. PxTapiAccept(
  443. IN PNDISTAPI_REQUEST pNdisTapiRequest
  444. )
  445. /*++
  446. Routine Description:
  447. Placeholder for TAPI OID action routines
  448. Arguments:
  449. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  450. Return Value:
  451. --*/
  452. {
  453. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAccept: enter\n"));
  454. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAccept: exit\n"));
  455. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  456. }
  457. NDIS_STATUS
  458. PxTapiAnswer(
  459. IN PNDISTAPI_REQUEST pNdisTapiRequest
  460. )
  461. /*++
  462. Routine Description:
  463. Placeholder for TAPI OID action routines
  464. Arguments:
  465. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  466. Return Value:
  467. --*/
  468. {
  469. PNDIS_TAPI_ANSWER pNdisTapiAnswer;
  470. PPX_VC pVc = NULL;
  471. NDIS_STATUS Status;
  472. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAnswer: enter\n"));
  473. pNdisTapiAnswer =
  474. (PNDIS_TAPI_ANSWER)pNdisTapiRequest->Data;
  475. if (!IsVcValid(pNdisTapiAnswer->hdCall, &pVc)) {
  476. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiAnswer: pVc invalid call handle %d\n",
  477. pNdisTapiAnswer->hdCall));
  478. return(NDIS_STATUS_TAPI_INVALCALLHANDLE);
  479. }
  480. NdisAcquireSpinLock(&pVc->Lock);
  481. do {
  482. if (pVc->State != PX_VC_OFFERING) {
  483. //
  484. // call in wrong state
  485. //
  486. PXDEBUGP(PXD_FATAL, PXM_TAPI, ("PxTapiAnswer: pVc VC %x/%x invalid state %x\n",
  487. pVc, pVc->Flags,
  488. pVc->ulCallState));
  489. NdisReleaseSpinLock(&pVc->Lock);
  490. Status = NDIS_STATUS_TAPI_INVALCALLSTATE;
  491. break;
  492. }
  493. if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
  494. PxStopIncomingCallTimeout(pVc);
  495. }
  496. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  497. ("PxTapiAnswer: calling NdisClIncomingCallComplete\n"));
  498. pVc->PrevState = pVc->State;
  499. pVc->State = PX_VC_CONNECTED;
  500. NdisReleaseSpinLock(&pVc->Lock);
  501. NdisClIncomingCallComplete (NDIS_STATUS_SUCCESS,
  502. pVc->ClVcHandle,
  503. pVc->pCallParameters);
  504. } while (FALSE);
  505. //
  506. // Deref for ref applied at entry when
  507. // validating the vc
  508. //
  509. DEREF_VC(pVc);
  510. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiAnswer: exit\n"));
  511. return (NDIS_STATUS_SUCCESS);
  512. }
  513. NDIS_STATUS
  514. PxTapiLineGetID(
  515. IN PNDISTAPI_REQUEST pNdisTapiRequest
  516. )
  517. /*++
  518. Routine Description:
  519. Returns a handle to the client wich is returned to the tapi application.
  520. This handle is only meaning full to the client and will vary depending
  521. on the deviceclass.
  522. Arguments:
  523. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  524. Return Value:
  525. --*/
  526. {
  527. PNDIS_TAPI_GET_ID pNdisTapiGetId =
  528. (PNDIS_TAPI_GET_ID)pNdisTapiRequest->Data;
  529. PVAR_STRING DeviceID = &pNdisTapiGetId->DeviceID;
  530. PPX_VC pVc = NULL;
  531. NDIS_HANDLE VcHandle = NULL;
  532. PPX_CM_AF pCmAf;
  533. PPX_CM_SAP pCmSap;
  534. NDIS_STATUS Status;
  535. LPCWSTR DevClass;
  536. ULONG DevClassSize;
  537. PPX_ADAPTER pAdapter;
  538. DevClass =
  539. (LPCWSTR)(((CHAR *)pNdisTapiGetId) + pNdisTapiGetId->ulDeviceClassOffset);
  540. DevClassSize = pNdisTapiGetId->ulDeviceClassSize;
  541. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiLineGetID: enter. CallId %x, DevClass = %ls\n", pNdisTapiGetId->hdCall, DevClass));
  542. if (pNdisTapiGetId->ulSelect != LINECALLSELECT_CALL) {
  543. return (NDIS_STATUS_FAILURE);
  544. }
  545. //
  546. // validate call handle and get call pointer
  547. //
  548. if (!IsVcValid(pNdisTapiGetId->hdCall, &pVc)) {
  549. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxNdisTapiGetId: pVc invalid call handle %d\n",
  550. pNdisTapiGetId->hdCall));
  551. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  552. }
  553. NdisAcquireSpinLock(&pVc->Lock);
  554. do {
  555. //
  556. // ToDo!
  557. //
  558. // If we already are working with a client
  559. // we need to see if this is a mapping to the same
  560. // client or to a different one. If it is to the
  561. // same one just return the current handle. If it
  562. // is to a different one we should either fail or
  563. // tear the vc hand-off down from the current client
  564. // and then hand-off to the new client.
  565. //
  566. if (pVc->CmVcHandle != NULL) {
  567. Status = NDIS_STATUS_SUCCESS;
  568. break;
  569. }
  570. if (pVc->State != PX_VC_CONNECTED) {
  571. Status = NDIS_STATUS_TAPI_INVALCALLSTATE;
  572. break;
  573. }
  574. pAdapter = pVc->Adapter;
  575. //
  576. // Find the sap/af of the client that we need to indicate this on
  577. //
  578. if (!PxAfAndSapFromDevClass(pAdapter,
  579. DevClass,
  580. &pCmAf,
  581. &pCmSap)) {
  582. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  583. ("PxTapiLineGetID: SAP not found!\n"));
  584. Status = NDIS_STATUS_FAILURE;
  585. break;
  586. }
  587. pVc->HandoffState = PX_VC_HANDOFF_OFFERING;
  588. pVc->CmAf = pCmAf;
  589. pVc->CmSap = pCmSap;
  590. VcHandle = pVc->ClVcHandle;
  591. NdisReleaseSpinLock(&pVc->Lock);
  592. //
  593. // Create the Vc
  594. //
  595. Status = NdisCoCreateVc(pAdapter->CmBindingHandle,
  596. pCmAf->NdisAfHandle,
  597. (NDIS_HANDLE)pVc->hdCall,
  598. &VcHandle);
  599. if (Status != NDIS_STATUS_SUCCESS) {
  600. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  601. ("PxTapiLineGetID: Client refused Vc CmAf %p DevClass %ls Status %x\n",
  602. pCmAf, DevClass, Status));
  603. Status = NDIS_STATUS_FAILURE;
  604. //
  605. // remove ref that was applied when we mapped the devclass
  606. // to an af/sap.
  607. //
  608. DEREF_CM_AF(pCmAf);
  609. NdisAcquireSpinLock(&pVc->Lock);
  610. pVc->HandoffState = PX_VC_HANDOFF_IDLE;
  611. break;
  612. }
  613. NdisAcquireSpinLock(&pVc->Lock);
  614. pVc->CmVcHandle = VcHandle;
  615. //
  616. // Apply a reference on the vc for
  617. // activating this call with the client.
  618. // This ref is removed in PxCmCloseCall.
  619. //
  620. REF_VC(pVc);
  621. NdisReleaseSpinLock(&pVc->Lock);
  622. //
  623. // Dispatch the incoming call to the client
  624. //
  625. Status =
  626. NdisCmDispatchIncomingCall(pCmSap->NdisSapHandle,
  627. pVc->CmVcHandle,
  628. pVc->pCallParameters);
  629. if (Status == NDIS_STATUS_PENDING) {
  630. Status = PxBlock(&pVc->Block);
  631. }
  632. if (Status != NDIS_STATUS_SUCCESS) {
  633. //
  634. // The client did not except the call
  635. // delete the vc and go away.
  636. //
  637. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  638. ("PxTapiLineGetID: Client rejected call VC %p, Status %x\n",
  639. pVc, Status));
  640. #ifdef CODELETEVC_FIXED
  641. //
  642. // Evidently the CoCreateVc is unbalanced
  643. // when creating a proxy vc. The call to
  644. // NdisCoDeleteVc will fail because the
  645. // Vc is still active.
  646. // ToDo! Investigate this with ndis
  647. //
  648. Status =
  649. NdisCoDeleteVc(pVc->CmVcHandle);
  650. #endif
  651. //
  652. // remove ref that was applied when we mapped the devclass
  653. // to an af/sap.
  654. //
  655. DEREF_CM_AF(pCmAf);
  656. NdisAcquireSpinLock(&pVc->Lock);
  657. #ifdef CODELETEVC_FIXED
  658. if (Status == NDIS_STATUS_SUCCESS) {
  659. pVc->CmVcHandle = NULL;
  660. }
  661. #endif
  662. pVc->HandoffState = PX_VC_HANDOFF_IDLE;
  663. //
  664. // Remove the reference we applied before
  665. // dispatching incoming call to client.
  666. // We do not need to do all of the deref code
  667. // because of the ref applied at entry to
  668. // this function
  669. //
  670. pVc->RefCount--;
  671. break;
  672. }
  673. NdisCmDispatchCallConnected(pVc->CmVcHandle);
  674. NdisAcquireSpinLock(&pVc->Lock);
  675. //
  676. // If we are still in the offering state
  677. // we can safely move to connected at this
  678. // point. We might not be in offering if
  679. // right after we connected the client
  680. // did an NdisClCloseCall before we could
  681. // reacquire the spinlock.
  682. //
  683. if (pVc->HandoffState == PX_VC_HANDOFF_OFFERING) {
  684. pVc->HandoffState = PX_VC_HANDOFF_CONNECTED;
  685. }
  686. } while (FALSE);
  687. //
  688. // If we get here and we are not in the connected
  689. // state something happened to tear our call
  690. // down with the client. This could have been
  691. // an error attempting to create the call with the
  692. // client or we received either a
  693. // tapidrop from tapi
  694. // incomingclosecall from cm
  695. //
  696. if (pVc->State != PX_VC_CONNECTED) {
  697. Status =
  698. PxCloseCallWithCl(pVc);
  699. if ((Status != NDIS_STATUS_PENDING) &&
  700. (pVc->Flags & PX_VC_CLEANUP_CM)) {
  701. PxCloseCallWithCm(pVc);
  702. }
  703. Status = NDIS_STATUS_FAILURE;
  704. } else if (Status == NDIS_STATUS_SUCCESS) {
  705. Status = NdisCoGetTapiCallId(pVc->CmVcHandle,
  706. DeviceID);
  707. //
  708. // ToDo?: If status is failure here, do we need to do anything? In our
  709. // case this should be OK, because the TSP ensures the size of
  710. // the VAR_STRING is right, and that's the only thing that can
  711. // cause a failure.
  712. //
  713. }
  714. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  715. ("PxTapiLineGetID: Vc %p, Status %x\n", pVc, Status));
  716. //
  717. // Deref for ref applied at entry when
  718. // validating the vc
  719. //
  720. DEREF_VC_LOCKED(pVc);
  721. return Status;
  722. }
  723. NDIS_STATUS
  724. PxTapiClose (
  725. IN PNDISTAPI_REQUEST pNdisTapiRequest
  726. )
  727. /*++
  728. Routine Description:
  729. TAPI is closing it's handle to our device. We shouldn't see any further requests or
  730. send any TAPI events after completing this function.
  731. In the current design, we are the sole owner of all VCs (i.e. there are no 'pass-through' or monitor-only
  732. functions in the Proxy). TAPI should not call this func before all calls have been closed and all apps
  733. have disconnected.
  734. NOTE: this function is also called by TAPI after we send it a LINE_REMOVE message, indicating that
  735. the adapter has been unbound. In this case, too, we should already have closed all calls/freed VCs and
  736. associated structures.
  737. Arguments:
  738. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  739. Return Value:
  740. --*/
  741. {
  742. PNDIS_TAPI_CLOSE pTapiClose =
  743. (PNDIS_TAPI_CLOSE)pNdisTapiRequest->Data;
  744. PPX_TAPI_LINE TapiLine;
  745. PPX_VC pVc;
  746. PPX_TAPI_PROVIDER TapiProvider;
  747. PPX_CL_SAP pClSap;
  748. PPX_CL_AF pClAf;
  749. NDIS_STATUS Status;
  750. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  751. ("PxTapiClose: ID: %d\n", pTapiClose->hdLine));
  752. //
  753. // validate line handle and get line pointer
  754. //
  755. if (!IsTapiLineValid((ULONG)pTapiClose->hdLine, &TapiLine)) {
  756. PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiClose: NDISTAPIERR_BADDEVICEID: line = %x\n", pTapiClose->hdLine));
  757. return (NDISTAPIERR_BADDEVICEID);
  758. }
  759. NdisAcquireSpinLock(&TapiLine->Lock);
  760. TapiLine->DevStatus->ulNumOpens--;
  761. if (TapiLine->DevStatus->ulNumOpens != 0) {
  762. NdisReleaseSpinLock(&TapiLine->Lock);
  763. return (NDIS_STATUS_SUCCESS);
  764. }
  765. pClAf = TapiLine->ClAf;
  766. pClSap = TapiLine->ClSap;
  767. TapiLine->ClSap = NULL;
  768. TapiLine->DevStatus->ulOpenMediaModes = 0;
  769. NdisReleaseSpinLock(&TapiLine->Lock);
  770. //
  771. // If we have any active Vc's on this line we need
  772. // tear them down.
  773. //
  774. if (pClAf != NULL) {
  775. NdisAcquireSpinLock(&pClAf->Lock);
  776. REF_CL_AF(pClAf);
  777. #if 0
  778. while (!IsListEmpty(&pClAf->VcList)) {
  779. PLIST_ENTRY Entry;
  780. PPX_VC pActiveVc;
  781. Entry = RemoveHeadList(&pClAf->VcList);
  782. InsertHeadList(&pClAf->VcClosingList, Entry);
  783. pActiveVc =
  784. CONTAINING_RECORD(Entry, PX_VC, ClAfLinkage);
  785. NdisReleaseSpinLock(&pClAf->Lock);
  786. NdisAcquireSpinLock(&pActiveVc->Lock);
  787. if (!(pActiveVc->CloseFlags & PX_VC_TAPI_CLOSE)) {
  788. REF_VC(pActiveVc);
  789. pActiveVc->CloseFlags |= PX_VC_TAPI_CLOSE;
  790. PxVcCleanup(pActiveVc, 0);
  791. PxTapiCompleteAllIrps(pActiveVc, NDIS_STATUS_SUCCESS);
  792. //
  793. // Remove the ref applied in the make call or call offering
  794. // indication. We do not need the full deref code because
  795. // of the ref applied at entry.
  796. //
  797. pActiveVc->RefCount--;
  798. DEREF_VC_LOCKED(pActiveVc);
  799. }
  800. NdisAcquireSpinLock(&pClAf->Lock);
  801. }
  802. #endif
  803. //
  804. // If we have a sap registered on this line we need
  805. // to close it.
  806. //
  807. if (pClSap != NULL) {
  808. // If the SAP is opened then we need to close it
  809. if (pClSap->State == PX_SAP_OPENED) {
  810. RemoveEntryList(&pClSap->Linkage);
  811. InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
  812. NdisReleaseSpinLock(&pClAf->Lock);
  813. InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
  814. Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
  815. if (Status != NDIS_STATUS_PENDING) {
  816. PxClDeregisterSapComplete(Status, pClSap);
  817. }
  818. NdisAcquireSpinLock(&pClAf->Lock);
  819. }
  820. }
  821. DEREF_CL_AF_LOCKED(pClAf);
  822. }
  823. DEREF_TAPILINE(TapiLine);
  824. return(NDIS_STATUS_SUCCESS);
  825. }
  826. NDIS_STATUS
  827. PxTapiCloseCall(
  828. IN PNDISTAPI_REQUEST pNdisTapiRequest
  829. )
  830. /*++
  831. Routine Description:
  832. for TAPI OID action routines
  833. Arguments:
  834. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  835. Return Value:
  836. --*/
  837. {
  838. NDIS_STATUS Status;
  839. PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall =
  840. (PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequest->Data;
  841. PPX_VC pVc;
  842. PPX_TAPI_LINE TapiLine;
  843. if (!IsVcValid(pNdisTapiCloseCall->hdCall, &pVc)) {
  844. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiCloseCall: invalid call handle %d\n",
  845. pNdisTapiCloseCall->hdCall));
  846. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  847. }
  848. PXDEBUGP (PXD_TAPI, PXM_TAPI,
  849. ("PxTapiCloseCall: enter. VC = %x, State = %x\n",
  850. pVc, pVc->State));
  851. NdisAcquireSpinLock(&pVc->Lock);
  852. pVc->CloseFlags |= PX_VC_TAPI_CLOSECALL;
  853. //
  854. // Check the Vc state and act accordingly
  855. //
  856. PxVcCleanup(pVc, 0);
  857. PxTapiCompleteAllIrps(pVc, NDIS_STATUS_SUCCESS);
  858. //
  859. // Remove the ref applied in the make call or call offering
  860. // indication. We do not need the full deref code because
  861. // of the ref applied at entry.
  862. //
  863. pVc->RefCount--;
  864. //
  865. // Deref for ref applied at entry when
  866. // validating the vc
  867. //
  868. DEREF_VC_LOCKED(pVc);
  869. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiCloseCall: exit.\n"));
  870. return (NDIS_STATUS_SUCCESS);
  871. }
  872. NDIS_STATUS
  873. PxTapiConditionalMediaDetection(
  874. IN PNDISTAPI_REQUEST pNdisTapiRequest
  875. )
  876. /*++
  877. Routine Description:
  878. Placeholder for TAPI OID action routines
  879. Arguments:
  880. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  881. Return Value:
  882. --*/
  883. {
  884. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConditionalMediaDetection: enter\n"));
  885. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConditionalMediaDetection: exit\n"));
  886. return (NDIS_STATUS_SUCCESS);
  887. }
  888. NDIS_STATUS
  889. PxTapiConfigDialog (
  890. IN PNDISTAPI_REQUEST pNdisTapiRequest
  891. )
  892. /*++
  893. Routine Description:
  894. Placeholder for TAPI OID action routines
  895. Arguments:
  896. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  897. Return Value:
  898. --*/
  899. {
  900. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConfigDialog: enter\n"));
  901. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConfigDialog: exit\n"));
  902. return (NDIS_STATUS_SUCCESS);
  903. }
  904. NDIS_STATUS
  905. PxTapiDevSpecific(
  906. IN PNDISTAPI_REQUEST pNdisTapiRequest
  907. )
  908. /*++
  909. Routine Description:
  910. D for TAPI OID action routines
  911. Arguments:
  912. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  913. Return Value:
  914. --*/
  915. {
  916. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDevSpecific: enter\n"));
  917. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDevSpecific: exit\n"));
  918. return (NDIS_STATUS_SUCCESS);
  919. }
  920. NDIS_STATUS
  921. PxTapiDial(
  922. IN PNDISTAPI_REQUEST pNdisTapiRequest
  923. )
  924. /*++
  925. Routine Description:
  926. Placeholder for TAPI OID action routines
  927. Arguments:
  928. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  929. Return Value:
  930. --*/
  931. {
  932. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDial: enter\n"));
  933. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDial: exit\n"));
  934. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  935. }
  936. NDIS_STATUS
  937. PxTapiDrop(
  938. IN PNDISTAPI_REQUEST pNdisTapiRequest
  939. )
  940. /*++
  941. Routine Description:
  942. Drop the call without deallocating the VC.
  943. Arguments:
  944. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  945. Return Value:
  946. --*/
  947. {
  948. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  949. PPX_VC pVc;
  950. PIRP Irp;
  951. PNDIS_TAPI_DROP pNdisTapiDrop =
  952. (PNDIS_TAPI_DROP)pNdisTapiRequest->Data;
  953. if (!IsVcValid(pNdisTapiDrop->hdCall, &pVc)) {
  954. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiDrop: invalid call handle %d\n",
  955. pNdisTapiDrop->hdCall));
  956. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  957. }
  958. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  959. ("PxTapiDrop enter: Vc: %p VcState: %x CallState: %x\n", pVc, pVc->State, pVc->ulCallState ));
  960. NdisAcquireSpinLock(&pVc->Lock);
  961. Irp = pNdisTapiRequest->Irp;
  962. IoSetCancelRoutine(Irp, PxCancelSetQuery);
  963. //
  964. // Insert the request in the Vc's pending list
  965. //
  966. InsertTailList(&pVc->PendingDropReqs,
  967. &pNdisTapiRequest->Linkage);
  968. pVc->CloseFlags |= PX_VC_TAPI_DROP;
  969. //
  970. // Check the Vc state and act accordingly
  971. //
  972. Status =
  973. PxVcCleanup(pVc, PX_VC_DROP_PENDING);
  974. if (Status != NDIS_STATUS_PENDING) {
  975. RemoveEntryList(&pNdisTapiRequest->Linkage);
  976. IoSetCancelRoutine(Irp, NULL);
  977. }
  978. //
  979. // Deref for ref applied at entry when
  980. // validating the vc
  981. //
  982. DEREF_VC_LOCKED(pVc);
  983. return (Status);
  984. }
  985. NDIS_STATUS
  986. PxTapiGetAddressCaps(
  987. IN PNDISTAPI_REQUEST pNdisTapiRequest
  988. )
  989. /*++
  990. Routine Description:
  991. Placeholder for TAPI OID action routines
  992. Arguments:
  993. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  994. Return Value:
  995. --*/
  996. {
  997. PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps =
  998. (PNDIS_TAPI_GET_ADDRESS_CAPS) pNdisTapiRequest->Data;
  999. PPX_TAPI_LINE TapiLine;
  1000. PPX_TAPI_ADDR TapiAddr;
  1001. PPX_ADAPTER ClAdapter;
  1002. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1003. if (!IsTapiDeviceValid(pNdisTapiRequest->ulDeviceID, &TapiLine)) {
  1004. PXDEBUGP (PXD_WARNING, PXM_TAPI, ( "PxTapiGetAddressCaps: NDISTAPIERR_BADDEVICEID: line = %x\n", pNdisTapiRequest->ulDeviceID));
  1005. return (NDISTAPIERR_BADDEVICEID);
  1006. }
  1007. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  1008. ("PxTapiGetAddressCaps: got device %p from ID %d\n",
  1009. TapiLine, pNdisTapiRequest->ulDeviceID));
  1010. NdisAcquireSpinLock(&TapiLine->Lock);
  1011. do {
  1012. ULONG DevClassesSize = 0;
  1013. USHORT DevClassesList[512];
  1014. ULONG SizeToMove;
  1015. ULONG TotalSize;
  1016. ULONG SizeLeft;
  1017. PLINE_ADDRESS_CAPS In, Out;
  1018. //
  1019. // Get the tapi address that we are interested in
  1020. //
  1021. if (!IsAddressValid(TapiLine,
  1022. pNdisTapiGetAddressCaps->ulAddressID,
  1023. &TapiAddr)) {
  1024. Status = NDIS_STATUS_TAPI_INVALADDRESSID;
  1025. break;
  1026. }
  1027. In = TapiAddr->Caps;
  1028. Out = &pNdisTapiGetAddressCaps->LineAddressCaps;
  1029. //
  1030. // Add some space for our device classes
  1031. //
  1032. DevClassesSize = sizeof(DevClassesList);
  1033. NdisZeroMemory((PUCHAR)DevClassesList,
  1034. sizeof(DevClassesList));
  1035. if (TapiLine->TapiProvider->Adapter != NULL) {
  1036. GetAllDevClasses(TapiLine->TapiProvider->Adapter,
  1037. DevClassesList,
  1038. &DevClassesSize);
  1039. }
  1040. //
  1041. // Synchronously get Address caps for this device
  1042. //
  1043. SizeToMove = (In->ulUsedSize > Out->ulTotalSize) ?
  1044. Out->ulTotalSize : In->ulUsedSize;
  1045. TotalSize = Out->ulTotalSize;
  1046. NdisMoveMemory((PUCHAR)Out, (PUCHAR)In, SizeToMove);
  1047. SizeLeft =
  1048. TotalSize - SizeToMove;
  1049. Out->ulTotalSize = TotalSize;
  1050. Out->ulUsedSize = SizeToMove;
  1051. Out->ulNeededSize =
  1052. In->ulUsedSize + DevClassesSize;
  1053. if (SizeLeft > 0) {
  1054. //
  1055. // If these is room fill in our devclasses
  1056. //
  1057. if (DevClassesSize > 0) {
  1058. PUCHAR dst;
  1059. dst = (PUCHAR)Out + Out->ulUsedSize;
  1060. SizeToMove = (SizeLeft > DevClassesSize) ?
  1061. DevClassesSize : SizeLeft;
  1062. NdisMoveMemory(dst, DevClassesList, SizeToMove);
  1063. Out->ulDeviceClassesSize = SizeToMove;
  1064. Out->ulDeviceClassesOffset =
  1065. (ULONG)((ULONG_PTR)dst - (ULONG_PTR)Out);
  1066. Out->ulUsedSize += SizeToMove;
  1067. SizeLeft -= SizeToMove;
  1068. }
  1069. }
  1070. } while (FALSE);
  1071. DEREF_TAPILINE_LOCKED(TapiLine);
  1072. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetAddressCaps: exit. \n"));
  1073. return (Status);
  1074. }
  1075. NDIS_STATUS
  1076. PxTapiGetAddressID(
  1077. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. Placeholder for TAPI OID action routines
  1082. Arguments:
  1083. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1084. Return Value:
  1085. --*/
  1086. {
  1087. PNDIS_TAPI_GET_ADDRESS_ID TapiBuffer =
  1088. (PNDIS_TAPI_GET_ADDRESS_ID) pNdisTapiRequest->Data;
  1089. PPX_TAPI_LINE TapiLine;
  1090. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: enter\n"));
  1091. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  1092. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetAddressID: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
  1093. return(NDISTAPIERR_BADDEVICEID);
  1094. }
  1095. NdisAcquireSpinLock(&TapiLine->Lock);
  1096. //
  1097. // ToDo!
  1098. //
  1099. TapiBuffer->ulAddressID = 0;
  1100. DEREF_TAPILINE_LOCKED(TapiLine);
  1101. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: exit\n"));
  1102. return (NDIS_STATUS_SUCCESS);
  1103. }
  1104. NDIS_STATUS
  1105. PxTapiGetAddressStatus(
  1106. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Placeholder for TAPI OID action routines
  1111. Arguments:
  1112. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1113. Return Value:
  1114. --*/
  1115. {
  1116. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: enter\n"));
  1117. //
  1118. // ToDo!
  1119. //
  1120. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: exit\n"));
  1121. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1122. }
  1123. NDIS_STATUS
  1124. PxTapiGetCallAddressID(
  1125. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. TAPI OID action routine
  1130. Arguments:
  1131. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1132. Return Value:
  1133. --*/
  1134. {
  1135. PNDIS_TAPI_GET_CALL_ADDRESS_ID TapiBuffer =
  1136. (PNDIS_TAPI_GET_CALL_ADDRESS_ID)pNdisTapiRequest->Data;
  1137. PPX_VC pVc;
  1138. if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
  1139. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallAddressID: invalid call handle %d\n",
  1140. TapiBuffer->hdCall));
  1141. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1142. }
  1143. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: Vc: %p\n", pVc));
  1144. NdisAcquireSpinLock(&pVc->Lock);
  1145. TapiBuffer->ulAddressID = pVc->TapiAddr->AddrId;
  1146. DEREF_VC_LOCKED(pVc);
  1147. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: exit\n"));
  1148. return (NDIS_STATUS_SUCCESS);
  1149. }
  1150. NDIS_STATUS
  1151. PxTapiGetCallInfo(
  1152. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1153. )
  1154. /*++
  1155. Routine Description:
  1156. TAPI OID action routine
  1157. Arguments:
  1158. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1159. Return Value:
  1160. --*/
  1161. {
  1162. PNDIS_TAPI_GET_CALL_INFO TapiBuffer =
  1163. (PNDIS_TAPI_GET_CALL_INFO)pNdisTapiRequest->Data;
  1164. PPX_VC pVc;
  1165. PPX_TAPI_LINE TapiLine;
  1166. LINE_CALL_INFO* CallInfo;
  1167. LINE_CALL_INFO* OutCallInfo = &TapiBuffer->LineCallInfo;
  1168. ULONG VarDataSize = 0; // Total available
  1169. ULONG VarDataUsed = 0;
  1170. if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
  1171. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallInfo: invalid call handle %d\n",
  1172. TapiBuffer->hdCall));
  1173. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1174. }
  1175. NdisAcquireSpinLock(&pVc->Lock);
  1176. //
  1177. // Make sure we have enough space to copy everything over
  1178. //
  1179. CallInfo = pVc->CallInfo;
  1180. TapiLine = pVc->TapiLine;
  1181. VarDataSize =
  1182. pNdisTapiRequest->ulDataSize - sizeof(NDIS_TAPI_GET_CALL_INFO);
  1183. PXDEBUGP (PXD_TAPI, PXM_TAPI,
  1184. ("PxTapiGetCallInfo: enter. pVc = %p, AvailSize = %x, needed = %x\n",
  1185. pVc, OutCallInfo->ulTotalSize, CallInfo->ulUsedSize));
  1186. OutCallInfo->ulNeededSize = CallInfo->ulUsedSize;
  1187. //
  1188. // Patch up the Id here. We store it in our callinfo
  1189. // block in terms of the call managers 0 based Id. We
  1190. // need to give tapi the Id it is looking for which is
  1191. // stored in the tapiline.
  1192. //
  1193. OutCallInfo->ulLineDeviceID = TapiLine->ulDeviceID;
  1194. OutCallInfo->ulAddressID = CallInfo->ulAddressID;
  1195. OutCallInfo->ulBearerMode = CallInfo->ulBearerMode;
  1196. OutCallInfo->ulRate = CallInfo->ulRate;
  1197. OutCallInfo->ulMediaMode = CallInfo->ulMediaMode;
  1198. OutCallInfo->ulAppSpecific = CallInfo->ulAppSpecific;
  1199. OutCallInfo->ulCallID = 0;
  1200. OutCallInfo->ulRelatedCallID = 0;
  1201. OutCallInfo->ulCallParamFlags = 0;
  1202. OutCallInfo->DialParams.ulDialPause = 0;
  1203. OutCallInfo->DialParams.ulDialSpeed = 0;
  1204. OutCallInfo->DialParams.ulDigitDuration = 0;
  1205. OutCallInfo->DialParams.ulWaitForDialtone = 0;
  1206. OutCallInfo->ulReason = CallInfo->ulReason;
  1207. OutCallInfo->ulCompletionID = 0;
  1208. OutCallInfo->ulCountryCode = 0;
  1209. OutCallInfo->ulTrunk = (ULONG)-1;
  1210. //
  1211. // Do the CallerID
  1212. //
  1213. if (CallInfo->ulCallerIDSize) {
  1214. if (((VarDataUsed + CallInfo->ulCallerIDSize) <= VarDataSize) &&
  1215. ((CallInfo->ulCallerIDOffset + CallInfo->ulCallerIDSize) <= CallInfo->ulUsedSize)) {
  1216. OutCallInfo->ulCallerIDSize = CallInfo->ulCallerIDSize;
  1217. OutCallInfo->ulCallerIDFlags = CallInfo->ulCallerIDFlags;
  1218. OutCallInfo->ulCallerIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
  1219. NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCallerIDOffset,
  1220. (PUCHAR)(CallInfo)+CallInfo->ulCallerIDOffset,
  1221. CallInfo->ulCallerIDSize);
  1222. VarDataUsed += CallInfo->ulCallerIDSize;
  1223. pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLERID;
  1224. }
  1225. } else {
  1226. OutCallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL;
  1227. OutCallInfo->ulCallerIDSize = 0;
  1228. OutCallInfo->ulCallerIDOffset = 0;
  1229. }
  1230. OutCallInfo->ulCallerIDNameSize = 0;
  1231. OutCallInfo->ulCallerIDNameOffset = 0;
  1232. //
  1233. // Do the CalledID
  1234. //
  1235. if (CallInfo->ulCalledIDSize) {
  1236. if (((VarDataUsed + CallInfo->ulCalledIDSize) <= VarDataSize) &&
  1237. ((CallInfo->ulCalledIDOffset + CallInfo->ulCalledIDSize) <= CallInfo->ulUsedSize)) {
  1238. OutCallInfo->ulCalledIDFlags = CallInfo->ulCalledIDFlags;
  1239. OutCallInfo->ulCalledIDSize = CallInfo->ulCalledIDSize;
  1240. OutCallInfo->ulCalledIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
  1241. NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCalledIDOffset,
  1242. (PUCHAR)(CallInfo)+CallInfo->ulCalledIDOffset,
  1243. CallInfo->ulCalledIDSize);
  1244. VarDataUsed += CallInfo->ulCalledIDSize;
  1245. pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLEDID;
  1246. }
  1247. } else {
  1248. OutCallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL;
  1249. OutCallInfo->ulCalledIDSize = 0;
  1250. OutCallInfo->ulCalledIDOffset = 0;
  1251. }
  1252. OutCallInfo->ulCalledIDNameSize = 0;
  1253. OutCallInfo->ulCalledIDNameOffset = 0;
  1254. OutCallInfo->ulCallStates = LINECALLSTATE_IDLE |
  1255. LINECALLSTATE_OFFERING |
  1256. LINECALLSTATE_CONNECTED |
  1257. LINECALLSTATE_PROCEEDING |
  1258. LINECALLSTATE_DISCONNECTED |
  1259. LINECALLSTATE_SPECIALINFO |
  1260. LINECALLSTATE_UNKNOWN;
  1261. OutCallInfo->ulOrigin = (pVc->Flags & PX_VC_OWNER) ? LINECALLORIGIN_EXTERNAL : LINECALLORIGIN_OUTBOUND;
  1262. OutCallInfo->ulReason = LINECALLREASON_UNAVAIL;
  1263. OutCallInfo->ulCompletionID = 0;
  1264. OutCallInfo->ulConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
  1265. OutCallInfo->ulConnectedIDSize = 0;
  1266. OutCallInfo->ulConnectedIDOffset = 0;
  1267. OutCallInfo->ulConnectedIDNameSize = 0;
  1268. OutCallInfo->ulConnectedIDNameOffset = 0;
  1269. OutCallInfo->ulRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
  1270. OutCallInfo->ulRedirectionIDSize = 0;
  1271. OutCallInfo->ulRedirectionIDOffset = 0;
  1272. OutCallInfo->ulRedirectionIDNameSize = 0;
  1273. OutCallInfo->ulRedirectionIDNameOffset = 0;
  1274. OutCallInfo->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  1275. OutCallInfo->ulRedirectingIDSize = 0;
  1276. OutCallInfo->ulRedirectingIDOffset = 0;
  1277. OutCallInfo->ulRedirectingIDNameSize = 0;
  1278. OutCallInfo->ulRedirectingIDNameOffset = 0;
  1279. OutCallInfo->ulDisplaySize = 0;
  1280. OutCallInfo->ulDisplayOffset = 0;
  1281. OutCallInfo->ulUserUserInfoSize = 0;
  1282. OutCallInfo->ulUserUserInfoOffset = 0;
  1283. OutCallInfo->ulHighLevelCompSize = 0;
  1284. OutCallInfo->ulHighLevelCompOffset = 0;
  1285. OutCallInfo->ulLowLevelCompSize = 0;
  1286. OutCallInfo->ulLowLevelCompOffset = 0;
  1287. OutCallInfo->ulChargingInfoSize = 0;
  1288. OutCallInfo->ulChargingInfoOffset = 0;
  1289. OutCallInfo->ulTerminalModesSize = 0;
  1290. OutCallInfo->ulTerminalModesOffset = 0;
  1291. OutCallInfo->ulDevSpecificSize = 0;
  1292. OutCallInfo->ulDevSpecificOffset = 0;
  1293. OutCallInfo->ulNeededSize =
  1294. OutCallInfo->ulUsedSize = sizeof(LINE_CALL_INFO) + VarDataUsed;
  1295. //
  1296. // Deref for ref applied at entry when
  1297. // validating the vc
  1298. //
  1299. DEREF_VC_LOCKED(pVc);
  1300. return (NDIS_STATUS_SUCCESS);
  1301. }
  1302. NDIS_STATUS
  1303. PxTapiGetCallStatus (
  1304. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. TAPI OID action routine
  1309. Arguments:
  1310. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1311. Return Value:
  1312. --*/
  1313. {
  1314. PNDIS_TAPI_GET_CALL_STATUS TapiBuffer =
  1315. (PNDIS_TAPI_GET_CALL_STATUS)pNdisTapiRequest->Data;
  1316. PPX_VC pVc;
  1317. LINE_CALL_INFO* CallInfo;
  1318. LINE_CALL_STATUS* CallStatus = &TapiBuffer->LineCallStatus;
  1319. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallStatus: enter\n"));\
  1320. if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
  1321. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallStatus: invalid call handle %d\n",
  1322. TapiBuffer->hdCall));
  1323. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1324. }
  1325. NdisAcquireSpinLock(&pVc->Lock);
  1326. CallInfo = pVc->CallInfo;
  1327. CallStatus->ulUsedSize = sizeof(LINE_CALL_STATUS);
  1328. CallStatus->ulCallState = pVc->ulCallState;
  1329. //
  1330. // fill the mode depending on the call state
  1331. //
  1332. switch (pVc->ulCallState) {
  1333. case LINECALLSTATE_IDLE:
  1334. default:
  1335. CallStatus->ulCallStateMode = 0;
  1336. CallStatus->ulCallFeatures = 0;
  1337. break;
  1338. case LINECALLSTATE_CONNECTED:
  1339. CallStatus->ulCallStateMode = 0;
  1340. CallStatus->ulCallFeatures = LINECALLFEATURE_DROP;
  1341. break;
  1342. case LINECALLSTATE_OFFERING:
  1343. CallStatus->ulCallStateMode = 0;
  1344. CallStatus->ulCallFeatures = LINECALLFEATURE_ANSWER;
  1345. break;
  1346. case LINECALLSTATE_DISCONNECTED:
  1347. if (pVc->ulCallStateMode == 0x11 )
  1348. CallStatus->ulCallStateMode = LINEDISCONNECTMODE_BUSY;
  1349. else
  1350. CallStatus->ulCallStateMode = LINEDISCONNECTMODE_NOANSWER;
  1351. break;
  1352. case LINECALLSTATE_BUSY:
  1353. CallStatus->ulCallStateMode = LINEBUSYMODE_UNAVAIL;
  1354. break;
  1355. case LINECALLSTATE_SPECIALINFO:
  1356. // if(cm->NoActiveLine)
  1357. // CallStatus->ulCallStateMode = LINESPECIALINFO_NOCIRCUIT;
  1358. CallStatus->ulCallStateMode = 0;
  1359. break;
  1360. }
  1361. CallStatus->ulDevSpecificSize = 0;
  1362. CallStatus->ulDevSpecificOffset = 0;
  1363. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("GetCallStatus: VC %x/%x, CallSt %x, Mode %x, Features %x\n",
  1364. pVc, pVc->Flags,
  1365. CallStatus->ulCallState,
  1366. CallStatus->ulCallStateMode,
  1367. CallStatus->ulCallFeatures));
  1368. //
  1369. // Deref for ref applied at entry when
  1370. // validating the vc
  1371. //
  1372. DEREF_VC_LOCKED(pVc);
  1373. return (NDIS_STATUS_SUCCESS);
  1374. }
  1375. NDIS_STATUS
  1376. PxTapiGetDevConfig(
  1377. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1378. )
  1379. /*++
  1380. Routine Description:
  1381. TAPI OID action routine
  1382. Arguments:
  1383. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1384. Return Value:
  1385. --*/
  1386. {
  1387. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: enter\n"));
  1388. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: exit\n"));
  1389. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1390. }
  1391. NDIS_STATUS
  1392. PxTapiGetExtensionID(
  1393. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1394. )
  1395. /*++
  1396. Routine Description:
  1397. TAPI OID action routine
  1398. Arguments:
  1399. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1400. Return Value:
  1401. --*/
  1402. {
  1403. PNDIS_TAPI_GET_EXTENSION_ID TapiBuffer = (PNDIS_TAPI_GET_EXTENSION_ID)pNdisTapiRequest->Data;
  1404. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: enter\n"));
  1405. // TapiBuffer->LineExtensionID.ulExtensionID0 = 0;
  1406. // TapiBuffer->LineExtensionID.ulExtensionID1 = 0;
  1407. // TapiBuffer->LineExtensionID.ulExtensionID2 = 0;
  1408. // TapiBuffer->LineExtensionID.ulExtensionID3 = 0;
  1409. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: exit\n"));
  1410. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1411. }
  1412. NDIS_STATUS
  1413. PxTapiGetLineDevStatus(
  1414. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1415. )
  1416. /*++
  1417. Routine Description:
  1418. TAPI OID action routine
  1419. Arguments:
  1420. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1421. Return Value:
  1422. --*/
  1423. {
  1424. PNDIS_TAPI_GET_LINE_DEV_STATUS TapiBuffer =
  1425. (PNDIS_TAPI_GET_LINE_DEV_STATUS)pNdisTapiRequest->Data;
  1426. PPX_TAPI_LINE TapiLine;
  1427. PX_ADAPTER *pAdapter;
  1428. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: enter\n"));
  1429. //
  1430. // validate line handle and get line pointer
  1431. //
  1432. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  1433. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
  1434. return (NDISTAPIERR_BADDEVICEID);
  1435. }
  1436. NdisAcquireSpinLock(&TapiLine->Lock);
  1437. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: got device %p from ID %d\n", TapiLine, TapiBuffer->hdLine));
  1438. //
  1439. // Get MediaModes and Current Calls
  1440. //
  1441. TapiBuffer->LineDevStatus.ulOpenMediaModes =
  1442. TapiLine->DevStatus->ulOpenMediaModes;
  1443. TapiBuffer->LineDevStatus.ulNumActiveCalls =
  1444. TapiLine->DevStatus->ulNumActiveCalls;
  1445. TapiBuffer->LineDevStatus.ulDevStatusFlags =
  1446. TapiLine->DevStatus->ulDevStatusFlags;
  1447. DEREF_TAPILINE_LOCKED(TapiLine);
  1448. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: exit\n"));
  1449. return (NDIS_STATUS_SUCCESS);
  1450. }
  1451. NDIS_STATUS
  1452. PxTapiNegotiateExtVersion(
  1453. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1454. )
  1455. /*++
  1456. Routine Description:
  1457. TAPI OID action routine
  1458. Arguments:
  1459. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1460. Return Value:
  1461. --*/
  1462. {
  1463. PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion =
  1464. (PNDIS_TAPI_NEGOTIATE_EXT_VERSION) pNdisTapiRequest->Data;
  1465. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: enter\n"));
  1466. pNdisTapiNegotiateExtVersion->ulExtVersion = 0;
  1467. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: exit NDIS_STATUS_TAPI_OPERATIONUNAVAIL\n"));
  1468. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1469. }
  1470. NDIS_STATUS
  1471. PxTapiSendUserUserInfo(
  1472. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1473. )
  1474. /*++
  1475. Routine Description:
  1476. TAPI OID action routine
  1477. Arguments:
  1478. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1479. Return Value:
  1480. --*/
  1481. {
  1482. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: enter\n"));
  1483. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: exit\n"));
  1484. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1485. }
  1486. NDIS_STATUS
  1487. PxTapiSetAppSpecific(
  1488. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1489. )
  1490. /*++
  1491. Routine Description:
  1492. TAPI OID action routine
  1493. Arguments:
  1494. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1495. Return Value:
  1496. --*/
  1497. {
  1498. PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific =
  1499. (PNDIS_TAPI_SET_APP_SPECIFIC)(pNdisTapiRequest->Data);
  1500. PPX_VC pVc;
  1501. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: enter\n"));
  1502. if (!IsVcValid(pNdisTapiSetAppSpecific->hdCall, &pVc)) {
  1503. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetAppSpecific: pVc invalid call handle %d\n",
  1504. pNdisTapiSetAppSpecific->hdCall));
  1505. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1506. }
  1507. NdisAcquireSpinLock(&pVc->Lock);
  1508. //
  1509. // Get the VC, and re-set the app specific longword.
  1510. //
  1511. pVc->CallInfo->ulAppSpecific =
  1512. pNdisTapiSetAppSpecific->ulAppSpecific;
  1513. //
  1514. // Deref for ref applied at entry when
  1515. // validating the vc
  1516. //
  1517. DEREF_VC_LOCKED(pVc);
  1518. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: exit\n"));
  1519. return (NDIS_STATUS_SUCCESS);
  1520. }
  1521. NDIS_STATUS
  1522. PxTapiSetCallParams(
  1523. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. TAPI OID action routine
  1528. Arguments:
  1529. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1530. Return Value:
  1531. --*/
  1532. {
  1533. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: enter\n"));
  1534. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: exit\n"));
  1535. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1536. }
  1537. NDIS_STATUS
  1538. PxTapiSetDefaultMediaDetection(
  1539. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1540. )
  1541. /*++
  1542. Routine Description:
  1543. TAPI OID action routine
  1544. Arguments:
  1545. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1546. Return Value:
  1547. --*/
  1548. {
  1549. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION TapiBuffer =
  1550. (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)pNdisTapiRequest->Data;
  1551. PPX_CL_AF pClAf = NULL;
  1552. PPX_CL_SAP pClSap = NULL;
  1553. PCO_SAP pCoSap;
  1554. PPX_TAPI_LINE TapiLine = NULL;
  1555. NDIS_STATUS Status;
  1556. BOOLEAN Found = FALSE;
  1557. PPX_TAPI_PROVIDER TapiProvider;
  1558. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: enter\n"));
  1559. //
  1560. // validate line handle and get line pointer
  1561. //
  1562. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  1563. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1564. ("PxTapiSetDefaultMediaDetection: NDISTAPIERR_BADDEVICEID: line = %x\n",
  1565. TapiBuffer->hdLine));
  1566. return (NDISTAPIERR_BADDEVICEID);
  1567. }
  1568. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  1569. ("PxTapiSetDefaultMediaDetection: got TapiLine %p from ID %d\n",
  1570. TapiLine, TapiBuffer->hdLine));
  1571. NdisAcquireSpinLock(&TapiLine->Lock);
  1572. do {
  1573. //
  1574. // Is this line in service? (does it have an valid af?)
  1575. //
  1576. if (!(TapiLine->DevStatus->ulDevStatusFlags &
  1577. LINEDEVSTATUSFLAGS_INSERVICE)) {
  1578. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1579. ("PxTapiSetDefaultMediaDetection: Line not in service!\n"));
  1580. NdisReleaseSpinLock(&TapiLine->Lock);
  1581. Status = NDIS_STATUS_TAPI_INVALLINESTATE;
  1582. break;
  1583. }
  1584. //
  1585. // Make sure this line supports these media modes
  1586. //
  1587. if ((TapiBuffer->ulMediaModes & TapiLine->DevCaps->ulMediaModes) !=
  1588. TapiBuffer->ulMediaModes) {
  1589. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1590. ("PxTapiSetDefaultMediaDetection: invalid media mode\n"));
  1591. NdisReleaseSpinLock(&TapiLine->Lock);
  1592. Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
  1593. break;
  1594. }
  1595. //
  1596. // See if we already have these media modes open
  1597. //
  1598. if ((TapiBuffer->ulMediaModes &
  1599. ~TapiLine->DevStatus->ulOpenMediaModes) == 0) {
  1600. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1601. ("PxTapiSetDefaultMediaDetection: Already have a sap!\n"));
  1602. NdisReleaseSpinLock(&TapiLine->Lock);
  1603. Status = NDIS_STATUS_SUCCESS;
  1604. break;
  1605. }
  1606. TapiLine->DevStatus->ulOpenMediaModes |=
  1607. TapiBuffer->ulMediaModes;
  1608. pClAf = TapiLine->ClAf;
  1609. pClSap = TapiLine->ClSap;
  1610. TapiLine->ClSap = NULL;
  1611. NdisReleaseSpinLock(&TapiLine->Lock);
  1612. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1613. ("PxTapiSetDefaultMediaDetection: TapiLine: %p, pClAf: %p, MediaModes: %x\n",
  1614. TapiLine, pClAf, TapiLine->DevStatus->ulOpenMediaModes));
  1615. NdisAcquireSpinLock(&pClAf->Lock);
  1616. REF_CL_AF(pClAf);
  1617. if (pClSap != NULL) {
  1618. //
  1619. // We already have a sap on this line. We only need one
  1620. // per line so let's deregister the old one before registering
  1621. // the new one.
  1622. //
  1623. RemoveEntryList(&pClSap->Linkage);
  1624. InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
  1625. NdisReleaseSpinLock(&pClAf->Lock);
  1626. InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
  1627. Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
  1628. if (Status != NDIS_STATUS_PENDING) {
  1629. PxClDeregisterSapComplete(Status, pClSap);
  1630. }
  1631. } else {
  1632. NdisReleaseSpinLock(&pClAf->Lock);
  1633. }
  1634. //
  1635. // Get a SAP translation for this Media Mode setting.
  1636. // The function is called with the Af lock held and
  1637. // returns with the Af lock released!
  1638. //
  1639. pClSap = (*pClAf->AfGetNdisSap)(pClAf, TapiLine);
  1640. if (pClSap == NULL) {
  1641. Status = NDIS_STATUS_RESOURCES;
  1642. break;
  1643. }
  1644. NdisAcquireSpinLock(&pClAf->Lock);
  1645. InsertTailList(&pClAf->ClSapList, &pClSap->Linkage);
  1646. REF_CL_AF(pClAf);
  1647. NdisReleaseSpinLock(&pClAf->Lock);
  1648. //
  1649. // Register the new sap
  1650. //
  1651. Status = NdisClRegisterSap(pClAf->NdisAfHandle,
  1652. pClSap,
  1653. pClSap->CoSap,
  1654. &pClSap->NdisSapHandle);
  1655. if (Status != NDIS_STATUS_PENDING) {
  1656. PxClRegisterSapComplete(Status,
  1657. pClSap,
  1658. pClSap->CoSap,
  1659. pClSap->NdisSapHandle);
  1660. }
  1661. } while (FALSE);
  1662. DEREF_CL_AF(pClAf);
  1663. DEREF_TAPILINE(TapiLine);
  1664. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: exit\n"));
  1665. return (NDIS_STATUS_SUCCESS);
  1666. }
  1667. NDIS_STATUS
  1668. PxTapiSetDevConfig(
  1669. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1670. )
  1671. /*++
  1672. Routine Description:
  1673. TAPI OID action routine
  1674. Arguments:
  1675. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1676. Return Value:
  1677. --*/
  1678. {
  1679. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: enter\n"));
  1680. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: exit\n"));
  1681. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1682. }
  1683. NDIS_STATUS
  1684. PxTapiSetMediaMode(
  1685. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. TAPI OID action routine
  1690. Arguments:
  1691. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1692. Return Value:
  1693. --*/
  1694. {
  1695. PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode =
  1696. (PNDIS_TAPI_SET_MEDIA_MODE)(pNdisTapiRequest->Data);
  1697. PPX_VC pVc;
  1698. PPX_TAPI_LINE TapiLine;
  1699. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1700. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: enter\n"));
  1701. if (!IsVcValid(pNdisTapiSetMediaMode->hdCall, &pVc)) {
  1702. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetMediaMode: pVc invalid call handle %d\n",
  1703. pNdisTapiSetMediaMode->hdCall));
  1704. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1705. }
  1706. NdisAcquireSpinLock(&pVc->Lock);
  1707. TapiLine = pVc->TapiAddr->TapiLine;
  1708. if ((TapiLine->DevCaps->ulMediaModes & pNdisTapiSetMediaMode->ulMediaMode)) {
  1709. pVc->CallInfo->ulMediaMode = pNdisTapiSetMediaMode->ulMediaMode;
  1710. } else {
  1711. Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
  1712. }
  1713. //
  1714. // Deref for ref applied at entry when
  1715. // validating the vc
  1716. //
  1717. DEREF_VC_LOCKED(pVc);
  1718. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: exit\n"));
  1719. return (Status);
  1720. }
  1721. NDIS_STATUS
  1722. PxTapiSetStatusMessages(
  1723. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. TAPI OID action routine
  1728. Arguments:
  1729. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1730. Return Value:
  1731. --*/
  1732. {
  1733. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSeStatusMessages: enter\n"));
  1734. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetStatusMessages: exit\n"));
  1735. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1736. }
  1737. NDIS_STATUS
  1738. PxTapiOpen(
  1739. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1740. )
  1741. /*++
  1742. Routine Description:
  1743. TAPI OID action routine
  1744. Arguments:
  1745. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1746. Return Value:
  1747. --*/
  1748. {
  1749. PNDIS_TAPI_OPEN TapiBuffer =
  1750. (PNDIS_TAPI_OPEN)pNdisTapiRequest->Data;
  1751. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1752. PPX_TAPI_LINE TapiLine;
  1753. PPX_TAPI_ADDR TapiAddr;
  1754. PNDISTAPI_OPENDATA OpenData;
  1755. PX_ADAPTER *Adapter;
  1756. ULONG n;
  1757. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: enter\nn"));
  1758. if (!IsTapiDeviceValid(TapiBuffer->ulDeviceID, &TapiLine)) {
  1759. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOPEN: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->ulDeviceID));
  1760. return(NDISTAPIERR_BADDEVICEID);
  1761. }
  1762. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiOpen: got device %p from ID %d\n", TapiLine, TapiBuffer->ulDeviceID));
  1763. NdisAcquireSpinLock(&TapiLine->Lock);
  1764. if (!(TapiLine->DevStatus->ulDevStatusFlags &
  1765. LINEDEVSTATUSFLAGS_INSERVICE)) {
  1766. NdisReleaseSpinLock(&TapiLine->Lock);
  1767. return(NDISTAPIERR_DEVICEOFFLINE);
  1768. }
  1769. //
  1770. // Stick TAPI's line handle into the device
  1771. //
  1772. TapiLine->htLine = (HTAPI_LINE)TapiBuffer->htLine;
  1773. TapiLine->DevStatus->ulNumOpens++;
  1774. //
  1775. // Stick our line handle into the out param. This is the context that will be
  1776. // passed to us in subsequent API calls on this open line device. Use the device ID.
  1777. //
  1778. TapiBuffer->hdLine = TapiLine->hdLine;
  1779. //
  1780. // Stick the miniport GUID and the mediatype into the variable data portion of the
  1781. // TAPI Open call (req'd for NDISWAN/Tonybe)
  1782. //
  1783. Adapter = TapiLine->TapiProvider->Adapter;
  1784. OpenData = (PNDISTAPI_OPENDATA)
  1785. ((PUCHAR)pNdisTapiRequest->Data + sizeof(NDIS_TAPI_OPEN));
  1786. RtlMoveMemory(&OpenData->Guid,
  1787. &Adapter->Guid,
  1788. sizeof(OpenData->Guid));
  1789. OpenData->MediaType = Adapter->MediumSubType;
  1790. DEREF_TAPILINE_LOCKED(TapiLine);
  1791. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: exit\n"));
  1792. return (NDIS_STATUS_SUCCESS);
  1793. }
  1794. NDIS_STATUS
  1795. PxTapiProviderInit(
  1796. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1797. )
  1798. /*++
  1799. Routine Description:
  1800. TAPI OID action routine
  1801. Arguments:
  1802. fea142c4
  1803. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1804. Return Value:
  1805. --*/
  1806. {
  1807. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: enter\n"));
  1808. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: exit\n"));
  1809. return (NDIS_STATUS_SUCCESS);
  1810. }
  1811. NDIS_STATUS
  1812. PxTapiProviderShutdown(
  1813. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1814. )
  1815. /*++
  1816. Routine Description:
  1817. TAPI OID action routine
  1818. Arguments:
  1819. fea142c4
  1820. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1821. Return Value:
  1822. --*/
  1823. {
  1824. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: enter\n"));
  1825. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: exit\n"));
  1826. return (NDIS_STATUS_SUCCESS);
  1827. }
  1828. NDIS_STATUS
  1829. PxTapiSecureCall(
  1830. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1831. )
  1832. /*++
  1833. Routine Description:
  1834. TAPI OID action routine
  1835. Arguments:
  1836. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1837. Return Value:
  1838. --*/
  1839. {
  1840. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: enter\n"));
  1841. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: exit\n"));
  1842. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1843. }
  1844. NDIS_STATUS
  1845. PxTapiSelectExtVersion(
  1846. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1847. )
  1848. /*++
  1849. Routine Description:
  1850. TAPI OID action routine
  1851. Arguments:
  1852. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1853. Return Value:
  1854. --*/
  1855. {
  1856. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: enter\n"));
  1857. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: exit\n"));
  1858. return (NDIS_STATUS_SUCCESS);
  1859. }
  1860. NDIS_STATUS
  1861. PxTapiGatherDigits(
  1862. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1863. )
  1864. {
  1865. NDIS_STATUS Status = STATUS_SUCCESS;
  1866. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits = NULL;
  1867. NDIS_HANDLE NdisBindingHandle, NdisAfHandle, NdisVcHandle;
  1868. PPX_VC pVc = NULL;
  1869. PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiGatherDigits: Enter\n"));
  1870. pNdisTapiGatherDigits =
  1871. (PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
  1872. do {
  1873. PX_REQUEST ProxyRequest;
  1874. PNDIS_REQUEST NdisRequest;
  1875. PIRP Irp;
  1876. if (!IsVcValid(pNdisTapiGatherDigits->hdCall, &pVc)) {
  1877. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  1878. ("PxTapiGatherDigits: Invalid call - Setting "
  1879. "Status NDISTAPIERR_BADDEVICEID\n"));
  1880. Status = NDISTAPIERR_BADDEVICEID;
  1881. break;
  1882. }
  1883. NdisAcquireSpinLock(&pVc->Lock);
  1884. //
  1885. // If we're monitoring digits (ala lineMonitorDigits) then we can't gather digits.
  1886. //
  1887. if (pVc->ulMonitorDigitsModes != 0) {
  1888. NdisReleaseSpinLock(&pVc->Lock);
  1889. Status = NDIS_STATUS_FAILURE;
  1890. break;
  1891. }
  1892. if (pVc->PendingGatherDigits != NULL) {
  1893. //
  1894. // Check if the buffer passed to TSPI_lineGatherDigits was NULL. If so, then this
  1895. // is a request to cancel digit gathering that was previously initiated. If not, then
  1896. // the app is trying to do two lineGatherDigits() operations at once and we have to
  1897. // fail this.
  1898. //
  1899. if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
  1900. pVc->PendingGatherDigits = NULL;
  1901. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
  1902. NdisReleaseSpinLock(&pVc->Lock);
  1903. Status = NDIS_STATUS_SUCCESS;
  1904. break;
  1905. } else {
  1906. NdisReleaseSpinLock(&pVc->Lock);
  1907. Status = NDIS_STATUS_FAILURE;
  1908. break;
  1909. }
  1910. } else if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
  1911. //
  1912. // Trying to cancel digit detection even though it wasn't started. Fail this.
  1913. //
  1914. NdisReleaseSpinLock(&pVc->Lock);
  1915. Status = NDIS_STATUS_FAILURE;
  1916. break;
  1917. }
  1918. Irp = pNdisTapiRequest->Irp;
  1919. IoSetCancelRoutine(Irp, PxCancelSetQuery);
  1920. //
  1921. // Store the unique request ID in the VC - this will be used later to retrieve the
  1922. // original IRP.
  1923. //
  1924. pVc->PendingGatherDigits = pNdisTapiRequest;
  1925. NdisReleaseSpinLock(&pVc->Lock);
  1926. //
  1927. // Initialize the timer that will be used to implement the digit timeouts.
  1928. //
  1929. NdisInitializeTimer(&pVc->DigitTimer,
  1930. PxDigitTimerRoutine,
  1931. (PVOID)pVc);
  1932. //
  1933. // Fill out our request structure.
  1934. //
  1935. NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
  1936. PxInitBlockStruc(&ProxyRequest.Block);
  1937. NdisRequest = &ProxyRequest.NdisRequest;
  1938. NdisRequest->RequestType =
  1939. NdisRequestSetInformation;
  1940. NdisRequest->DATA.SET_INFORMATION.Oid =
  1941. OID_CO_TAPI_REPORT_DIGITS;
  1942. NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
  1943. (PVOID)&pNdisTapiGatherDigits->ulDigitModes; // This is the NDIS_TAPI_GATHER_DIGITS structure
  1944. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
  1945. sizeof(pNdisTapiGatherDigits->ulDigitModes);
  1946. Status =
  1947. NdisCoRequest(pVc->Adapter->ClBindingHandle,
  1948. pVc->ClAf->NdisAfHandle,
  1949. pVc->ClVcHandle,
  1950. NULL,
  1951. NdisRequest);
  1952. if (Status == NDIS_STATUS_PENDING) {
  1953. Status = PxBlock(&ProxyRequest.Block);
  1954. }
  1955. if (Status != NDIS_STATUS_SUCCESS) {
  1956. NdisAcquireSpinLock(&pVc->Lock);
  1957. pVc->PendingGatherDigits = NULL;
  1958. IoSetCancelRoutine(Irp, NULL);
  1959. NdisReleaseSpinLock(&pVc->Lock);
  1960. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  1961. ("PxTapiGatherDigits: NdisCoRequest failed\n"));
  1962. break;
  1963. }
  1964. //
  1965. // Start the timer for the first digit timeout. Ref the VC here because otherwise it might
  1966. // go away before the timer fires.
  1967. //
  1968. if (pNdisTapiGatherDigits->ulFirstDigitTimeout) {
  1969. NdisAcquireSpinLock(&pVc->Lock);
  1970. REF_VC(pVc);
  1971. NdisReleaseSpinLock(&pVc->Lock);
  1972. NdisSetTimer(&pVc->DigitTimer,
  1973. pNdisTapiGatherDigits->ulFirstDigitTimeout);
  1974. }
  1975. //
  1976. // Set status to pending because this request just initiates the gathering of digits.
  1977. // The IRP will complete once all the digits come in.
  1978. //
  1979. Status = NDIS_STATUS_PENDING;
  1980. } while (FALSE);
  1981. DEREF_VC(pVc);
  1982. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  1983. ("PxTapiGatherDigits: Exit - Returning 0x%x\n", Status));
  1984. return (Status);
  1985. }
  1986. NDIS_STATUS
  1987. PxTapiMonitorDigits(
  1988. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1989. )
  1990. {
  1991. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1992. PNDIS_TAPI_MONITOR_DIGITS pNdisTapiMonitorDigits = NULL;
  1993. PPX_VC pVc = NULL;
  1994. PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Enter\n"));
  1995. pNdisTapiMonitorDigits =
  1996. (PNDIS_TAPI_MONITOR_DIGITS)pNdisTapiRequest->Data;
  1997. do {
  1998. if (!IsVcValid(pNdisTapiMonitorDigits->hdCall, &pVc)) {
  1999. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2000. ("PxTapiMonitorDigits: Invalid call - Setting "
  2001. "Status NDISTAPIERR_BADDEVICEID\n"));
  2002. Status = NDISTAPIERR_BADDEVICEID;
  2003. break;
  2004. }
  2005. NdisAcquireSpinLock(&pVc->Lock);
  2006. if (pVc->PendingGatherDigits != NULL) {
  2007. //
  2008. // Can't monitor digits while a lineGatherDigits request is in effect.
  2009. //
  2010. NdisReleaseSpinLock(&pVc->Lock);
  2011. Status = NDIS_STATUS_FAILURE;
  2012. break;
  2013. }
  2014. if (pVc->ulMonitorDigitsModes != 0) {
  2015. NdisReleaseSpinLock(&pVc->Lock);
  2016. //
  2017. // We are already monitoring digits as a result of lineMonitorDigits request.
  2018. // If the digit modes in the this request are zero, then this is a request to
  2019. // cancel digit monitoring.
  2020. //
  2021. if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
  2022. Status = PxStopDigitReporting(pVc);
  2023. if (Status != NDIS_STATUS_SUCCESS) {
  2024. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2025. ("PxTapiMonitorDigits: Failed to stop digit reporting with status 0x%x\n", Status));
  2026. break;
  2027. }
  2028. //
  2029. // It's a shame that I have to acquire and release again since I had
  2030. // the lock before, but there's no way to know whether I can set this
  2031. // to zero until I know the status that PxStopDigitReporting() returned.
  2032. //
  2033. NdisAcquireSpinLock(&pVc->Lock);
  2034. pVc->ulMonitorDigitsModes = 0;
  2035. NdisReleaseSpinLock(&pVc->Lock);
  2036. } else {
  2037. //
  2038. // We're already monitoring digits, so this request to do so must fail.
  2039. //
  2040. Status = NDIS_STATUS_FAILURE;
  2041. break;
  2042. }
  2043. } else {
  2044. PX_REQUEST ProxyRequest;
  2045. PNDIS_REQUEST NdisRequest;
  2046. pVc->ulMonitorDigitsModes = pNdisTapiMonitorDigits->ulDigitModes;
  2047. NdisReleaseSpinLock(&pVc->Lock);
  2048. if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
  2049. //
  2050. // Someone's trying to cancel digit monitoring, but it hasn't been started yet.
  2051. //
  2052. Status = NDIS_STATUS_FAILURE;
  2053. break;
  2054. }
  2055. //
  2056. // Fill out our request structure to tell the miniport to start reporting digits.
  2057. //
  2058. NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
  2059. PxInitBlockStruc(&ProxyRequest.Block);
  2060. NdisRequest = &ProxyRequest.NdisRequest;
  2061. NdisRequest->RequestType =
  2062. NdisRequestSetInformation;
  2063. NdisRequest->DATA.SET_INFORMATION.Oid =
  2064. OID_CO_TAPI_REPORT_DIGITS;
  2065. NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
  2066. (PVOID)&pNdisTapiMonitorDigits->ulDigitModes;
  2067. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
  2068. sizeof(pNdisTapiMonitorDigits->ulDigitModes);
  2069. Status =
  2070. NdisCoRequest(pVc->Adapter->ClBindingHandle,
  2071. pVc->ClAf->NdisAfHandle,
  2072. pVc->ClVcHandle,
  2073. NULL,
  2074. NdisRequest);
  2075. if (Status == NDIS_STATUS_PENDING) {
  2076. Status = PxBlock(&ProxyRequest.Block);
  2077. }
  2078. if (Status != NDIS_STATUS_SUCCESS) {
  2079. NdisAcquireSpinLock(&pVc->Lock);
  2080. pVc->ulMonitorDigitsModes = 0;
  2081. NdisReleaseSpinLock(&pVc->Lock);
  2082. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2083. ("PxTapiMonitorDigits: NdisCoRequest to start digit reporting failed with status 0x%x\n", Status));
  2084. break;
  2085. }
  2086. }
  2087. } while (FALSE);
  2088. DEREF_VC(pVc);
  2089. PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Exit - Returning 0x%x\n", Status));
  2090. return (Status);
  2091. }
  2092. VOID
  2093. PxTapiCompleteDropIrps(
  2094. IN PPX_VC pVc,
  2095. IN ULONG Status
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. Arguments:
  2100. Return Value:
  2101. --*/
  2102. {
  2103. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: Vc %p\n", pVc));
  2104. ASSERT(!IsListEmpty(&pVc->PendingDropReqs));
  2105. ASSERT(pVc->Flags & PX_VC_DROP_PENDING);
  2106. while (!IsListEmpty(&pVc->PendingDropReqs)) {
  2107. PLIST_ENTRY Entry;
  2108. PIRP Irp;
  2109. KIRQL Irql;
  2110. PNDISTAPI_REQUEST pNdisTapiRequest;
  2111. Entry =
  2112. RemoveHeadList(&pVc->PendingDropReqs);
  2113. NdisReleaseSpinLock(&pVc->Lock);
  2114. pNdisTapiRequest =
  2115. CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
  2116. Irp = pNdisTapiRequest->Irp;
  2117. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  2118. IoSetCancelRoutine(Irp, NULL);
  2119. Irp->IoStatus.Information =
  2120. sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
  2121. Irp->IoStatus.Status = STATUS_SUCCESS;
  2122. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  2123. ("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
  2124. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2125. NdisAcquireSpinLock(&pVc->Lock);
  2126. }
  2127. pVc->Flags &= ~PX_VC_DROP_PENDING;
  2128. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: exit\n"));
  2129. return;
  2130. }
  2131. VOID
  2132. PxTapiCompleteAllIrps(
  2133. IN PPX_VC pVc,
  2134. IN ULONG Status
  2135. )
  2136. /*++
  2137. Routine Description:
  2138. Arguments:
  2139. Return Value:
  2140. --*/
  2141. {
  2142. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: Vc %p\n", pVc));
  2143. while (!IsListEmpty(&pVc->PendingDropReqs)) {
  2144. PLIST_ENTRY Entry;
  2145. PIRP Irp;
  2146. KIRQL Irql;
  2147. PNDISTAPI_REQUEST pNdisTapiRequest;
  2148. Entry =
  2149. RemoveHeadList(&pVc->PendingDropReqs);
  2150. NdisReleaseSpinLock(&pVc->Lock);
  2151. pNdisTapiRequest =
  2152. CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
  2153. Irp = pNdisTapiRequest->Irp;
  2154. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  2155. IoSetCancelRoutine(Irp, NULL);
  2156. Irp->IoStatus.Information =
  2157. sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
  2158. Irp->IoStatus.Status = STATUS_SUCCESS;
  2159. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  2160. ("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
  2161. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2162. NdisAcquireSpinLock(&pVc->Lock);
  2163. }
  2164. pVc->Flags &= ~PX_VC_DROP_PENDING;
  2165. if (pVc->PendingGatherDigits != NULL) {
  2166. PIRP Irp;
  2167. KIRQL Irql;
  2168. PNDISTAPI_REQUEST pNdisTapiRequest;
  2169. pNdisTapiRequest = pVc->PendingGatherDigits;
  2170. pVc->PendingGatherDigits = NULL;
  2171. NdisReleaseSpinLock(&pVc->Lock);
  2172. Irp = pNdisTapiRequest->Irp;
  2173. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  2174. IoSetCancelRoutine(Irp, NULL);
  2175. Irp->IoStatus.Information =
  2176. sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
  2177. Irp->IoStatus.Status = STATUS_SUCCESS;
  2178. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  2179. ("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
  2180. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2181. NdisAcquireSpinLock(&pVc->Lock);
  2182. }
  2183. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: exit\n"));
  2184. return;
  2185. }
  2186. VOID
  2187. PxIndicateStatus(
  2188. IN PVOID StatusBuffer,
  2189. IN UINT StatusBufferSize
  2190. )
  2191. /*++
  2192. Routine Description:
  2193. Called to send any event info that may be in the device extension to TAPI in the form of an
  2194. NDIS_TAPI_EVENT, sent in an available queued GET_EVENT IRP. If there's no outstanding IRP, stick
  2195. the data in the queue so it will go whenver there is one.
  2196. Arguments:
  2197. Return Value:
  2198. --*/
  2199. {
  2200. PIRP Irp;
  2201. PNDIS_TAPI_EVENT NdisTapiEvent;
  2202. PNDISTAPI_EVENT_DATA NdisTapiEventData;
  2203. NdisTapiEvent = StatusBuffer;
  2204. //
  2205. // Sync event buf access by acquiring EventSpinLock
  2206. //
  2207. NdisAcquireSpinLock(&TspCB.Lock);
  2208. //
  2209. // Are we initialized with TAPI?
  2210. //
  2211. if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
  2212. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2213. ("PxIndicateStatus: TAPI not connected!\n"));
  2214. NdisReleaseSpinLock(&TspCB.Lock);
  2215. return;
  2216. }
  2217. NdisReleaseSpinLock(&TspCB.Lock);
  2218. NdisAcquireSpinLock(&TspEventList.Lock);
  2219. Irp = TspEventList.RequestIrp;
  2220. TspEventList.RequestIrp = NULL;
  2221. if (Irp == NULL) {
  2222. PPROVIDER_EVENT ProviderEvent;
  2223. ProviderEvent =
  2224. ExAllocateFromNPagedLookasideList(&ProviderEventLookaside);
  2225. if (ProviderEvent != NULL) {
  2226. RtlMoveMemory(&ProviderEvent->Event,
  2227. StatusBuffer,
  2228. sizeof(NDIS_TAPI_EVENT));
  2229. InsertTailList(&TspEventList.List,
  2230. &ProviderEvent->Linkage);
  2231. TspEventList.Count++;
  2232. if (TspEventList.Count > TspEventList.MaxCount) {
  2233. TspEventList.MaxCount = TspEventList.Count;
  2234. }
  2235. }
  2236. } else {
  2237. ASSERT(IsListEmpty(&TspEventList.List));
  2238. }
  2239. NdisReleaseSpinLock(&TspEventList.Lock);
  2240. //
  2241. // Check of there is an outstanding request to satisfy
  2242. //
  2243. if (Irp != NULL) {
  2244. KIRQL Irql;
  2245. //
  2246. // Clear out the cancel routine
  2247. //
  2248. IoSetCancelRoutine (Irp, NULL);
  2249. Irp->IoStatus.Status = STATUS_SUCCESS;
  2250. Irp->IoStatus.Information =
  2251. sizeof(NDISTAPI_EVENT_DATA) + StatusBufferSize - 1;
  2252. //
  2253. // Copy as much of the input data possible from the input data
  2254. // queue to the SystemBuffer to satisfy the read.
  2255. //
  2256. NdisTapiEventData = Irp->AssociatedIrp.SystemBuffer;
  2257. ASSERT(NdisTapiEventData->ulTotalSize >= StatusBufferSize);
  2258. RtlMoveMemory(NdisTapiEventData->Data,
  2259. (PCHAR) StatusBuffer,
  2260. StatusBufferSize);
  2261. //
  2262. // Set the flag so that we start the next packet and complete
  2263. // this read request (with STATUS_SUCCESS) prior to return.
  2264. //
  2265. NdisTapiEventData->ulUsedSize = StatusBufferSize;
  2266. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  2267. ("PxIndicateStatus: htLine: %x, htCall: %x, Msg: %x\n",
  2268. NdisTapiEvent->htLine, NdisTapiEvent->htCall, NdisTapiEvent->ulMsg));
  2269. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  2270. (" : p1: %x, p2: %x, p3: %x\n",
  2271. NdisTapiEvent->ulParam1, NdisTapiEvent->ulParam2, NdisTapiEvent->ulParam3));
  2272. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  2273. }
  2274. }
  2275. NDIS_STATUS
  2276. AllocateTapiResources(
  2277. IN PPX_ADAPTER ClAdapter,
  2278. IN PPX_CL_AF pClAf
  2279. )
  2280. {
  2281. NDIS_STATUS Status;
  2282. ULONG SizeNeeded;
  2283. ULONG TapiVersion;
  2284. PPX_TAPI_LINE TapiLine = NULL;
  2285. PPX_TAPI_ADDR TapiAddr = NULL;
  2286. UINT i, j;
  2287. PPX_TAPI_PROVIDER TapiProvider;
  2288. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiResoures: Enter\n"));
  2289. //
  2290. // See if this device supports TAPI and if so
  2291. // see how many lines it has
  2292. //
  2293. TapiProvider =
  2294. AllocateTapiProvider(ClAdapter, pClAf);
  2295. if (TapiProvider == NULL) {
  2296. PXDEBUGP(PXD_ERROR, PXM_TAPI, ("Error allocating TapiProvider!\n"));
  2297. return (NDIS_STATUS_FAILURE);
  2298. }
  2299. return (NDIS_STATUS_SUCCESS);
  2300. }
  2301. PPX_TAPI_PROVIDER
  2302. AllocateTapiProvider(
  2303. PPX_ADAPTER ClAdapter,
  2304. PPX_CL_AF pClAf
  2305. )
  2306. {
  2307. PNDIS_REQUEST NdisRequest;
  2308. NDIS_STATUS Status;
  2309. CO_TAPI_CM_CAPS CmCaps;
  2310. BOOLEAN TapiSupported = TRUE;
  2311. ULONG AllocSize;
  2312. PTAPI_LINE_TABLE LineTable;
  2313. PPX_TAPI_PROVIDER TapiProvider = NULL;
  2314. ULONG i;
  2315. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiProvider: Enter\n"));
  2316. do {
  2317. PX_REQUEST ProxyRequest;
  2318. PPX_REQUEST pProxyRequest = &ProxyRequest;
  2319. NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
  2320. NdisZeroMemory(&CmCaps, sizeof(CmCaps));
  2321. PxInitBlockStruc (&pProxyRequest->Block);
  2322. NdisRequest = &pProxyRequest->NdisRequest;
  2323. NdisRequest->RequestType =
  2324. NdisRequestQueryInformation;
  2325. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2326. OID_CO_TAPI_CM_CAPS;
  2327. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2328. &CmCaps;
  2329. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2330. sizeof(CmCaps);
  2331. Status =
  2332. NdisCoRequest(ClAdapter->ClBindingHandle,
  2333. pClAf->NdisAfHandle,
  2334. NULL,
  2335. NULL,
  2336. NdisRequest);
  2337. if (Status == NDIS_STATUS_PENDING) {
  2338. Status = PxBlock(&pProxyRequest->Block);
  2339. }
  2340. if (Status != NDIS_STATUS_SUCCESS) {
  2341. if (Status != NDIS_STATUS_NOT_SUPPORTED) {
  2342. break;
  2343. }
  2344. Status = NDIS_STATUS_SUCCESS;
  2345. //
  2346. // Setup a default config for this device.
  2347. // ToDo! These values should be read from
  2348. // the registry on a per device basis!
  2349. //
  2350. CmCaps.ulNumLines = 1;
  2351. CmCaps.ulFlags = 0;
  2352. CmCaps.ulCoTapiVersion = CO_TAPI_VERSION;
  2353. TapiSupported = FALSE;
  2354. }
  2355. //
  2356. // Allocate a tapi provider block for this adapter
  2357. // The provider block will live outside of the
  2358. // adapter. This allows us to continue tapi service
  2359. // after a machine has been power managed.
  2360. //
  2361. AllocSize = sizeof(PX_TAPI_PROVIDER) +
  2362. (sizeof(PPX_TAPI_LINE) * CmCaps.ulNumLines) +
  2363. sizeof(PVOID);
  2364. PxAllocMem(TapiProvider, AllocSize, PX_PROVIDER_TAG);
  2365. if (TapiProvider == NULL) {
  2366. break;
  2367. }
  2368. NdisZeroMemory(TapiProvider, AllocSize);
  2369. NdisAllocateSpinLock(&TapiProvider->Lock);
  2370. TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
  2371. TapiProvider->Adapter = ClAdapter;
  2372. TapiProvider->ClAf = pClAf;
  2373. TapiProvider->NumDevices = CmCaps.ulNumLines;
  2374. TapiProvider->Guid = ClAdapter->Guid;
  2375. TapiProvider->Af = pClAf->Af;
  2376. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider Allocated: GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
  2377. TapiProvider->Guid.Data1, TapiProvider->Guid.Data2, TapiProvider->Guid.Data3,
  2378. TapiProvider->Guid.Data4[0],TapiProvider->Guid.Data4[1],TapiProvider->Guid.Data4[2],
  2379. TapiProvider->Guid.Data4[3],TapiProvider->Guid.Data4[4],TapiProvider->Guid.Data4[5],
  2380. TapiProvider->Guid.Data4[6],TapiProvider->Guid.Data4[7]));
  2381. TapiProvider->TapiSupported = TapiSupported;
  2382. TapiProvider->TapiFlags |= CmCaps.ulFlags;
  2383. TapiProvider->CoTapiVersion = CmCaps.ulCoTapiVersion;
  2384. InitializeListHead(&TapiProvider->LineList);
  2385. InitializeListHead(&TapiProvider->CreateList);
  2386. for (i = 0; i < TapiProvider->NumDevices; i++) {
  2387. PPX_TAPI_LINE TapiLine;
  2388. TapiLine =
  2389. AllocateTapiLine(TapiProvider, i);
  2390. if (TapiLine == NULL) {
  2391. FreeTapiProvider(TapiProvider);
  2392. TapiProvider = NULL;
  2393. break;
  2394. }
  2395. //
  2396. // Put the new line on the create list
  2397. // We will need to insert it in the line table
  2398. // and possibly notify tapi about it
  2399. //
  2400. InsertTailList(&TapiProvider->CreateList, &TapiLine->Linkage);
  2401. }
  2402. } while ( FALSE );
  2403. if (TapiProvider != NULL) {
  2404. PPX_TAPI_PROVIDER tp;
  2405. BOOLEAN TapiConnected;
  2406. //
  2407. // See if we already have a provider for this
  2408. // GUID. If we don't just add this provider on
  2409. // to the tsp and do the right thing with it's
  2410. // new lines. If we do see if anything on the
  2411. // provider has changed and do the right thing
  2412. // with it's tapi lines.
  2413. //
  2414. NdisAcquireSpinLock(&TspCB.Lock);
  2415. tp = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
  2416. while ((PVOID)tp != (PVOID)&TspCB.ProviderList) {
  2417. if ((tp->Status == PROVIDER_STATUS_OFFLINE) &&
  2418. (NdisEqualMemory(&tp->Guid, &TapiProvider->Guid, sizeof(tp->Guid))) &&
  2419. (pClAf->Af.AddressFamily == tp->Af.AddressFamily)) {
  2420. //
  2421. // We have already have a provider for this
  2422. // adapter/address family. See if anything has
  2423. // changed.
  2424. //
  2425. //
  2426. // ToDo!
  2427. // This check needs to be more complete!
  2428. //
  2429. if (tp->NumDevices != TapiProvider->NumDevices) {
  2430. //
  2431. // ToDo!
  2432. // Much work to do here!
  2433. //
  2434. } else {
  2435. //
  2436. // Nothing has changed so free the new allocations
  2437. // and reactivate the old ones.
  2438. //
  2439. FreeTapiProvider(TapiProvider);
  2440. TapiProvider = tp;
  2441. }
  2442. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider found: GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
  2443. ClAdapter->Guid.Data1, ClAdapter->Guid.Data2, ClAdapter->Guid.Data3,
  2444. ClAdapter->Guid.Data4[0],ClAdapter->Guid.Data4[1],ClAdapter->Guid.Data4[2],
  2445. ClAdapter->Guid.Data4[3],ClAdapter->Guid.Data4[4],ClAdapter->Guid.Data4[5],
  2446. ClAdapter->Guid.Data4[6],ClAdapter->Guid.Data4[7]));
  2447. break;
  2448. } else {
  2449. tp = (PPX_TAPI_PROVIDER)tp->Linkage.Flink;
  2450. }
  2451. }
  2452. //
  2453. // We did not find a provider on the list
  2454. // so insert the new provider
  2455. //
  2456. if ((PVOID)tp == (PVOID)&TspCB.ProviderList) {
  2457. InsertTailList(&TspCB.ProviderList, &TapiProvider->Linkage);
  2458. TspCB.NdisTapiNumDevices += TapiProvider->NumDevices;
  2459. }
  2460. if (TspCB.Status == NDISTAPI_STATUS_CONNECTED) {
  2461. TapiProvider->Status = PROVIDER_STATUS_ONLINE;
  2462. }
  2463. NdisReleaseSpinLock(&TspCB.Lock);
  2464. NdisAcquireSpinLock(&TapiProvider->Lock);
  2465. pClAf->TapiProvider = TapiProvider;
  2466. TapiProvider->ClAf= pClAf;
  2467. TapiProvider->Adapter = ClAdapter;
  2468. while (!IsListEmpty(&TapiProvider->CreateList)) {
  2469. PPX_TAPI_LINE TapiLine;
  2470. TapiLine = (PPX_TAPI_LINE)
  2471. RemoveHeadList(&TapiProvider->CreateList);
  2472. InsertTailList(&TapiProvider->LineList, &TapiLine->Linkage);
  2473. //
  2474. // Insert the line in the table
  2475. //
  2476. if (!InsertLineInTable(TapiLine)) {
  2477. FreeTapiLine(TapiLine);
  2478. continue;
  2479. }
  2480. NdisReleaseSpinLock(&TapiProvider->Lock);
  2481. SendTapiLineCreate(TapiLine);
  2482. NdisAcquireSpinLock(&TapiProvider->Lock);
  2483. }
  2484. MarkProviderOnline(TapiProvider);
  2485. NdisReleaseSpinLock(&TapiProvider->Lock);
  2486. }
  2487. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider: %x\n", TapiProvider));
  2488. return (TapiProvider);
  2489. }
  2490. VOID
  2491. MarkProviderOffline(
  2492. PPX_TAPI_PROVIDER TapiProvider
  2493. )
  2494. {
  2495. LOCK_STATE LockState;
  2496. ULONG i;
  2497. TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
  2498. TapiProvider->ClAf = NULL;
  2499. TapiProvider->Adapter = NULL;
  2500. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2501. for (i = 0; i < LineTable.Size; i++) {
  2502. PPX_TAPI_LINE TapiLine;
  2503. TapiLine = LineTable.Table[i];
  2504. if (TapiLine != NULL) {
  2505. NdisAcquireSpinLock(&TapiLine->Lock);
  2506. if (TapiLine->TapiProvider == TapiProvider) {
  2507. TapiLine->DevStatus->ulDevStatusFlags &=
  2508. ~(LINEDEVSTATUSFLAGS_INSERVICE);
  2509. TapiLine->ClAf = NULL;
  2510. NdisReleaseSpinLock(&TapiLine->Lock);
  2511. #if 0
  2512. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2513. SendTapiLineClose(TapiLine);
  2514. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2515. #endif
  2516. } else {
  2517. NdisReleaseSpinLock(&TapiLine->Lock);
  2518. }
  2519. }
  2520. }
  2521. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2522. }
  2523. VOID
  2524. MarkProviderOnline(
  2525. PPX_TAPI_PROVIDER TapiProvider
  2526. )
  2527. {
  2528. LOCK_STATE LockState;
  2529. ULONG i;
  2530. TapiProvider->Status = PROVIDER_STATUS_ONLINE;
  2531. NdisReleaseSpinLock(&TapiProvider->Lock);
  2532. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2533. for (i = 0; i < LineTable.Size; i++) {
  2534. PPX_TAPI_LINE TapiLine;
  2535. TapiLine = LineTable.Table[i];
  2536. if (TapiLine != NULL) {
  2537. NdisAcquireSpinLock(&TapiLine->Lock);
  2538. if (TapiLine->TapiProvider == TapiProvider) {
  2539. TapiLine->DevStatus->ulDevStatusFlags |=
  2540. LINEDEVSTATUSFLAGS_INSERVICE;
  2541. TapiLine->ClAf = TapiProvider->ClAf;
  2542. //#if 0
  2543. //
  2544. // This line was open by tapi before it was
  2545. // marked offline. We need to force tapi to
  2546. // reopen the line so we will send the CLOSE_LINE
  2547. // message in the hopes that any apps that care
  2548. // will then turn around and reopen the line.
  2549. //
  2550. if (TapiLine->DevStatus->ulNumOpens != 0) {
  2551. // TapiLine->DevStatus->ulNumOpens = 0;
  2552. NdisReleaseSpinLock(&TapiLine->Lock);
  2553. SendTapiLineClose(TapiLine);
  2554. NdisAcquireSpinLock(&TapiLine->Lock);
  2555. }
  2556. //#endif
  2557. }
  2558. NdisReleaseSpinLock(&TapiLine->Lock);
  2559. }
  2560. }
  2561. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2562. NdisAcquireSpinLock(&TapiProvider->Lock);
  2563. }
  2564. VOID
  2565. MarkProviderConnected(
  2566. PPX_TAPI_PROVIDER TapiProvider
  2567. )
  2568. {
  2569. LOCK_STATE LockState;
  2570. ULONG i;
  2571. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2572. for (i = 0; i < LineTable.Size; i++) {
  2573. PPX_TAPI_LINE TapiLine;
  2574. TapiLine = LineTable.Table[i];
  2575. if (TapiLine != NULL) {
  2576. NdisAcquireSpinLock(&TapiLine->Lock);
  2577. if (TapiLine->TapiProvider == TapiProvider) {
  2578. TapiLine->DevStatus->ulDevStatusFlags |=
  2579. LINEDEVSTATUSFLAGS_CONNECTED;
  2580. }
  2581. NdisReleaseSpinLock(&TapiLine->Lock);
  2582. }
  2583. }
  2584. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2585. }
  2586. VOID
  2587. MarkProviderDisconnected(
  2588. PPX_TAPI_PROVIDER TapiProvider
  2589. )
  2590. {
  2591. LOCK_STATE LockState;
  2592. ULONG i;
  2593. //
  2594. // ToDo! If we have any active calls on this line we
  2595. // need to disconnect them without tapi's assistance. This
  2596. // would only happen if tapi crashes while we have active calls
  2597. //
  2598. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2599. for (i = 0; i < LineTable.Size; i++) {
  2600. PPX_TAPI_LINE TapiLine;
  2601. TapiLine = LineTable.Table[i];
  2602. if (TapiLine != NULL) {
  2603. NdisAcquireSpinLock(&TapiLine->Lock);
  2604. if (TapiLine->TapiProvider == TapiProvider) {
  2605. TapiLine->DevStatus->ulDevStatusFlags &=
  2606. ~(LINEDEVSTATUSFLAGS_CONNECTED);
  2607. }
  2608. NdisReleaseSpinLock(&TapiLine->Lock);
  2609. }
  2610. }
  2611. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2612. }
  2613. VOID
  2614. ClearSapWithTapiLine(
  2615. PPX_CL_SAP pClSap
  2616. )
  2617. {
  2618. LOCK_STATE LockState;
  2619. ULONG i;
  2620. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2621. for (i = 0; i < LineTable.Size; i++) {
  2622. PPX_TAPI_LINE TapiLine;
  2623. TapiLine = LineTable.Table[i];
  2624. if (TapiLine != NULL) {
  2625. NdisAcquireSpinLock(&TapiLine->Lock);
  2626. if (TapiLine->ClSap == pClSap) {
  2627. TapiLine->ClSap = NULL;
  2628. }
  2629. NdisReleaseSpinLock(&TapiLine->Lock);
  2630. }
  2631. }
  2632. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2633. }
  2634. VOID
  2635. FreeTapiProvider(
  2636. PPX_TAPI_PROVIDER TapiProvider
  2637. )
  2638. {
  2639. //
  2640. // Free any lines on the create list
  2641. //
  2642. while (!IsListEmpty(&TapiProvider->CreateList)) {
  2643. PPX_TAPI_LINE TapiLine;
  2644. TapiLine = (PPX_TAPI_LINE)
  2645. RemoveHeadList(&TapiProvider->CreateList);
  2646. FreeTapiLine(TapiLine);
  2647. }
  2648. //
  2649. // Free the lines associated with this provider
  2650. //
  2651. while (!IsListEmpty(&TapiProvider->LineList)) {
  2652. PPX_TAPI_LINE TapiLine;
  2653. TapiLine = (PPX_TAPI_LINE)
  2654. RemoveHeadList(&TapiProvider->LineList);
  2655. if (TapiLine->Flags & PX_LINE_IN_TABLE) {
  2656. RemoveTapiLineFromTable(TapiLine);
  2657. }
  2658. FreeTapiLine(TapiLine);
  2659. }
  2660. NdisFreeSpinLock(&TapiProvider->Lock);
  2661. PxFreeMem(TapiProvider);
  2662. }
  2663. PPX_TAPI_LINE
  2664. AllocateTapiLine(
  2665. PPX_TAPI_PROVIDER TapiProvider,
  2666. ULONG LineNumber
  2667. )
  2668. {
  2669. PLINE_DEV_CAPS ldc, ldc1;
  2670. PNDIS_REQUEST NdisRequest;
  2671. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2672. PCO_TAPI_LINE_CAPS LineCaps;
  2673. PUCHAR EnumBuffer;
  2674. #if DBG
  2675. ULONG EnumBufferSize = PAGE_SIZE -
  2676. sizeof(PXD_ALLOCATION);
  2677. #else
  2678. ULONG EnumBufferSize = PAGE_SIZE;
  2679. #endif
  2680. ULONG SizeNeeded, SizeDevCaps;
  2681. PPX_TAPI_LINE TapiLine = NULL;
  2682. PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
  2683. PPX_CL_AF pClAf = TapiProvider->ClAf;
  2684. ULONG i;
  2685. PX_REQUEST ProxyRequest;
  2686. PPX_REQUEST pProxyRequest = &ProxyRequest;
  2687. PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
  2688. if (EnumBuffer == NULL) {
  2689. return (NULL);
  2690. }
  2691. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2692. LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
  2693. LineCaps->ulLineID = LineNumber;
  2694. ldc = &LineCaps->LineDevCaps;
  2695. ldc->ulTotalSize =
  2696. EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
  2697. //
  2698. // If this device does not support TAPI we will build
  2699. // a default line configuration.
  2700. // ToDo! Some of these values should be queried from
  2701. // the registry on a per device basis!
  2702. //
  2703. if (!TapiProvider->TapiSupported) {
  2704. NDIS_CO_LINK_SPEED SpeedInfo;
  2705. LineCaps->ulFlags = 0;
  2706. ldc->ulTotalSize =
  2707. ldc->ulNeededSize =
  2708. ldc->ulUsedSize =
  2709. sizeof(LINE_DEV_CAPS);
  2710. ldc->ulStringFormat = STRINGFORMAT_ASCII;
  2711. ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
  2712. ldc->ulNumAddresses = 1;
  2713. ldc->ulBearerModes = LINEBEARERMODE_VOICE |
  2714. LINEBEARERMODE_DATA;
  2715. ldc->ulMediaModes = LINEMEDIAMODE_DIGITALDATA;
  2716. ldc->ulMaxNumActiveCalls = 1000;
  2717. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  2718. PxInitBlockStruc (&pProxyRequest->Block);
  2719. NdisRequest = &pProxyRequest->NdisRequest;
  2720. NdisRequest->RequestType =
  2721. NdisRequestQueryInformation;
  2722. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2723. OID_GEN_CO_LINK_SPEED;
  2724. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2725. &SpeedInfo;
  2726. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2727. sizeof(NDIS_CO_LINK_SPEED);
  2728. PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: DeviceExtension->RegistryFlags = %x\n", DeviceExtension->RegistryFlags));
  2729. PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: using ndisrequest to get rates from adapter\n"));
  2730. Status =
  2731. NdisCoRequest(ClAdapter->ClBindingHandle,
  2732. pClAf->NdisAfHandle,
  2733. NULL,
  2734. NULL,
  2735. NdisRequest);
  2736. if (Status == NDIS_STATUS_PENDING) {
  2737. Status = PxBlock(&pProxyRequest->Block);
  2738. }
  2739. if (Status == NDIS_STATUS_SUCCESS) {
  2740. ldc->ulMaxRate = SpeedInfo.Outbound;
  2741. } else {
  2742. ldc->ulMaxRate = 128000;
  2743. }
  2744. } else if (!(TapiProvider->TapiFlags & CO_TAPI_FLAG_PER_LINE_CAPS) &&
  2745. (LineNumber > 0)) {
  2746. PLINE_DEV_CAPS ldc1;
  2747. PCO_TAPI_LINE_CAPS LineCaps1;
  2748. PPX_TAPI_LINE Line1;
  2749. //
  2750. // If all of the lines on this device have the same caps
  2751. // and this is not the first line, just copy the caps
  2752. // from the first line!
  2753. //
  2754. Line1 = (PPX_TAPI_LINE)
  2755. TapiProvider->CreateList.Flink;
  2756. ldc1 = Line1->DevCaps;
  2757. if (ldc1->ulTotalSize > ldc->ulTotalSize) {
  2758. //
  2759. // We don't have enough memory allocated!
  2760. //
  2761. PxFreeMem(EnumBuffer);
  2762. EnumBufferSize =
  2763. (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS) +
  2764. ldc1->ulTotalSize);
  2765. PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
  2766. if (EnumBuffer == NULL){
  2767. return (NULL);
  2768. }
  2769. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2770. LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
  2771. LineCaps->ulLineID = LineNumber;
  2772. LineCaps->LineDevCaps.ulTotalSize =
  2773. EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) -
  2774. sizeof(LINE_DEV_CAPS));
  2775. ldc = &LineCaps->LineDevCaps;
  2776. }
  2777. NdisMoveMemory(ldc, ldc1, ldc1->ulUsedSize);
  2778. } else {
  2779. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  2780. PxInitBlockStruc (&pProxyRequest->Block);
  2781. NdisRequest = &pProxyRequest->NdisRequest;
  2782. NdisRequest->RequestType =
  2783. NdisRequestQueryInformation;
  2784. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2785. OID_CO_TAPI_LINE_CAPS;
  2786. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2787. LineCaps;
  2788. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2789. EnumBufferSize;
  2790. Status =
  2791. NdisCoRequest(ClAdapter->ClBindingHandle,
  2792. pClAf->NdisAfHandle,
  2793. NULL,
  2794. NULL,
  2795. NdisRequest);
  2796. if (Status == NDIS_STATUS_PENDING) {
  2797. Status = PxBlock(&pProxyRequest->Block);
  2798. }
  2799. if (Status == NDIS_STATUS_INVALID_LENGTH){
  2800. ULONG SizeNeeded;
  2801. //
  2802. // Our buffer was not large enough so try again
  2803. //
  2804. SizeNeeded =
  2805. EnumBufferSize =
  2806. MAX (LineCaps->LineDevCaps.ulNeededSize,
  2807. NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
  2808. PxFreeMem(EnumBuffer);
  2809. PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
  2810. if (EnumBuffer == NULL){
  2811. return(NULL);
  2812. }
  2813. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2814. LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
  2815. LineCaps->ulLineID = LineNumber;
  2816. ldc = &LineCaps->LineDevCaps;
  2817. ldc->ulTotalSize =
  2818. EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
  2819. NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
  2820. PxInitBlockStruc (&pProxyRequest->Block);
  2821. NdisRequest = &pProxyRequest->NdisRequest;
  2822. NdisRequest->RequestType =
  2823. NdisRequestQueryInformation;
  2824. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2825. OID_CO_TAPI_LINE_CAPS;
  2826. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2827. LineCaps;
  2828. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2829. EnumBufferSize;
  2830. Status =
  2831. NdisCoRequest(ClAdapter->ClBindingHandle,
  2832. pClAf->NdisAfHandle,
  2833. NULL,
  2834. NULL,
  2835. NdisRequest);
  2836. if (Status == NDIS_STATUS_PENDING){
  2837. Status = PxBlock(&pProxyRequest->Block);
  2838. }
  2839. if (Status != NDIS_STATUS_SUCCESS){
  2840. PxFreeMem(EnumBuffer);
  2841. return(NULL);
  2842. }
  2843. }else if (Status != STATUS_SUCCESS){
  2844. PxFreeMem(EnumBuffer);
  2845. return(NULL);
  2846. }
  2847. }
  2848. SizeNeeded = sizeof(PX_TAPI_LINE);
  2849. SizeNeeded +=
  2850. (sizeof(PPX_TAPI_ADDR) * LineCaps->LineDevCaps.ulNumAddresses);
  2851. SizeNeeded += sizeof(LINE_DEV_STATUS);
  2852. SizeNeeded += 3*sizeof(PVOID);
  2853. if (LineCaps->LineDevCaps.ulUsedSize < sizeof(LINE_DEV_CAPS)) {
  2854. LineCaps->LineDevCaps.ulUsedSize = sizeof(LINE_DEV_CAPS);
  2855. }
  2856. SizeDevCaps = LineCaps->LineDevCaps.ulUsedSize;
  2857. SizeNeeded += SizeDevCaps;
  2858. PxAllocMem(TapiLine, SizeNeeded, PX_TAPILINE_TAG);
  2859. if (TapiLine == NULL){
  2860. PxFreeMem(EnumBuffer);
  2861. return(NULL);
  2862. }
  2863. NdisZeroMemory(TapiLine, SizeNeeded);
  2864. TapiLine->DevCaps = (PLINE_DEV_CAPS)
  2865. ((PUCHAR)TapiLine + sizeof(PX_TAPI_LINE) + sizeof(PVOID));
  2866. (ULONG_PTR)TapiLine->DevCaps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  2867. TapiLine->DevStatus = (PLINE_DEV_STATUS)
  2868. ((PUCHAR)TapiLine->DevCaps + SizeDevCaps + sizeof(PVOID));
  2869. (ULONG_PTR)TapiLine->DevStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  2870. TapiLine->AddrTable.Table = (PPX_TAPI_ADDR*)
  2871. ((PUCHAR)TapiLine->DevStatus +
  2872. sizeof(LINE_DEV_STATUS) + sizeof(PVOID));
  2873. (ULONG_PTR)TapiLine->AddrTable.Table &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  2874. NdisMoveMemory(TapiLine->DevCaps,
  2875. &LineCaps->LineDevCaps,
  2876. LineCaps->LineDevCaps.ulUsedSize);
  2877. ldc = TapiLine->DevCaps;
  2878. //
  2879. // Proxy fills some fields on behalf of all cm/miniports
  2880. //
  2881. ldc->ulPermanentLineID =
  2882. TapiProvider->Guid.Data1 + LineNumber;
  2883. ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
  2884. ldc->ulAnswerMode = LINEANSWERMODE_NONE;
  2885. ldc->ulLineStates = LINEDEVSTATE_CONNECTED |
  2886. LINEDEVSTATE_DISCONNECTED |
  2887. LINEDEVSTATE_OPEN |
  2888. LINEDEVSTATE_CLOSE |
  2889. LINEDEVSTATE_INSERVICE |
  2890. LINEDEVSTATE_OUTOFSERVICE |
  2891. LINEDEVSTATE_REMOVED;
  2892. ldc->ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
  2893. ldc->PermanentLineGuid = TapiProvider->Guid;
  2894. ldc->ulTotalSize =
  2895. ldc->ulNeededSize =
  2896. ldc->ulUsedSize;
  2897. TapiLine->TapiProvider = TapiProvider;
  2898. TapiLine->CmLineID = LineNumber;
  2899. TapiLine->Flags |= LineCaps->ulFlags;
  2900. TapiLine->DevStatus->ulTotalSize =
  2901. TapiLine->DevStatus->ulNeededSize =
  2902. TapiLine->DevStatus->ulUsedSize = sizeof(LINE_DEV_STATUS);
  2903. TapiLine->ClAf = pClAf;
  2904. TapiLine->RefCount= 1;
  2905. //
  2906. // Build the address table for this line
  2907. //
  2908. InitializeListHead(&TapiLine->AddrTable.List);
  2909. NdisAllocateSpinLock(&TapiLine->Lock);
  2910. TapiLine->AddrTable.Size = TapiLine->DevCaps->ulNumAddresses;
  2911. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  2912. ("Allocated TapiLine %p LineId %d \n", TapiLine, TapiLine->CmLineID));
  2913. for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++) {
  2914. PPX_TAPI_ADDR TapiAddr;
  2915. TapiAddr =
  2916. AllocateTapiAddr(TapiProvider, TapiLine, i);
  2917. if (TapiAddr == NULL) {
  2918. FreeTapiLine(TapiLine);
  2919. TapiLine = NULL;
  2920. break;
  2921. }
  2922. //
  2923. // Insert the address in the line's address table
  2924. //
  2925. TapiLine->AddrTable.Table[i] = TapiAddr;
  2926. InsertTailList(&TapiLine->AddrTable.List,
  2927. &TapiAddr->Linkage);
  2928. TapiLine->AddrTable.Count++;
  2929. }
  2930. PxFreeMem(EnumBuffer);
  2931. return (TapiLine);
  2932. }
  2933. VOID
  2934. FreeTapiLine(
  2935. PPX_TAPI_LINE TapiLine
  2936. )
  2937. {
  2938. ULONG i;
  2939. for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++){
  2940. PPX_TAPI_ADDR TapiAddr;
  2941. //
  2942. // Remove the address from the line table
  2943. //
  2944. TapiAddr = TapiLine->AddrTable.Table[i];
  2945. if (TapiAddr != NULL) {
  2946. RemoveEntryList(&TapiAddr->Linkage);
  2947. TapiLine->AddrTable.Table[i] = NULL;
  2948. TapiLine->AddrTable.Count--;
  2949. //
  2950. // Free the address memory
  2951. //
  2952. FreeTapiAddr(TapiAddr);
  2953. }
  2954. }
  2955. NdisFreeSpinLock(&TapiLine->Lock);
  2956. //
  2957. // Free the line memory
  2958. //
  2959. PxFreeMem(TapiLine);
  2960. }
  2961. PPX_TAPI_ADDR
  2962. AllocateTapiAddr(
  2963. PPX_TAPI_PROVIDER TapiProvider,
  2964. PPX_TAPI_LINE TapiLine,
  2965. ULONG AddrID
  2966. )
  2967. {
  2968. PPX_TAPI_ADDR TapiAddr;
  2969. PUCHAR EnumBuffer;
  2970. #if DBG
  2971. ULONG EnumBufferSize = PAGE_SIZE -
  2972. sizeof(PXD_ALLOCATION);
  2973. #else
  2974. ULONG EnumBufferSize = PAGE_SIZE;
  2975. #endif
  2976. PNDIS_REQUEST NdisRequest;
  2977. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2978. ULONG SizeNeeded;
  2979. PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
  2980. PPX_CL_AF pClAf = TapiProvider->ClAf;
  2981. PX_REQUEST ProxyRequest;
  2982. PPX_REQUEST pProxyRequest = &ProxyRequest;
  2983. PLINE_ADDRESS_CAPS ac;
  2984. PCO_TAPI_ADDRESS_CAPS AddrCaps;
  2985. PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
  2986. if (EnumBuffer == NULL){
  2987. return(NULL);
  2988. }
  2989. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2990. AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
  2991. AddrCaps->ulLineID = TapiLine->CmLineID;
  2992. AddrCaps->ulAddressID = AddrID;
  2993. ac = &AddrCaps->LineAddressCaps;
  2994. ac->ulTotalSize =
  2995. EnumBufferSize - (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
  2996. //
  2997. // If this device does not support TAPI we will
  2998. // build a default address.
  2999. // ToDo! Some of these values should be queried from
  3000. // the registry on a per device basis!
  3001. //
  3002. if (!TapiProvider->TapiSupported){
  3003. ac->ulTotalSize =
  3004. ac->ulNeededSize =
  3005. ac->ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
  3006. ac->ulMaxNumActiveCalls = 1000;
  3007. }else if (!(TapiLine->Flags & CO_TAPI_FLAG_PER_ADDRESS_CAPS) &&
  3008. (AddrID > 0)){
  3009. PLINE_ADDRESS_CAPS ac1;
  3010. PCO_TAPI_ADDRESS_CAPS AddrCaps1;
  3011. PPX_TAPI_ADDR Addr1;
  3012. //
  3013. // If all of the addresses on this line have the same
  3014. // caps and this is not the first address, just copy
  3015. // the caps from the first address!
  3016. //
  3017. Addr1 = (PPX_TAPI_ADDR)
  3018. TapiLine->AddrTable.List.Flink;
  3019. ac1 = Addr1->Caps;
  3020. if (ac1->ulTotalSize > ac->ulTotalSize){
  3021. //
  3022. // We don't have enough memory allocated!
  3023. //
  3024. PxFreeMem(EnumBuffer);
  3025. EnumBufferSize =
  3026. (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS) +
  3027. ac1->ulTotalSize);
  3028. PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
  3029. if (EnumBuffer == NULL){
  3030. return (NULL);
  3031. }
  3032. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  3033. AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
  3034. AddrCaps->ulLineID = TapiLine->CmLineID;
  3035. AddrCaps->ulAddressID = AddrID;
  3036. AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
  3037. (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
  3038. }
  3039. ac = &AddrCaps->LineAddressCaps;
  3040. NdisMoveMemory(ac, ac1, ac1->ulUsedSize);
  3041. }else{
  3042. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  3043. PxInitBlockStruc (&pProxyRequest->Block);
  3044. NdisRequest = &pProxyRequest->NdisRequest;
  3045. NdisRequest->RequestType =
  3046. NdisRequestQueryInformation;
  3047. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  3048. OID_CO_TAPI_ADDRESS_CAPS;
  3049. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  3050. AddrCaps;
  3051. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  3052. EnumBufferSize;
  3053. Status =
  3054. NdisCoRequest(ClAdapter->ClBindingHandle,
  3055. pClAf->NdisAfHandle,
  3056. NULL,
  3057. NULL,
  3058. NdisRequest);
  3059. if (Status == NDIS_STATUS_PENDING){
  3060. Status = PxBlock(&pProxyRequest->Block);
  3061. }
  3062. if (Status == NDIS_STATUS_INVALID_LENGTH){
  3063. //
  3064. // Our buffer was not large enough so try again
  3065. //
  3066. SizeNeeded =
  3067. EnumBufferSize =
  3068. NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
  3069. PxFreeMem(EnumBuffer);
  3070. PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
  3071. if (EnumBuffer == NULL){
  3072. return(NULL);
  3073. }
  3074. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  3075. AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
  3076. AddrCaps->ulLineID = TapiLine->CmLineID;
  3077. AddrCaps->ulAddressID = AddrID;
  3078. AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
  3079. (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
  3080. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  3081. PxInitBlockStruc (&pProxyRequest->Block);
  3082. NdisRequest = &pProxyRequest->NdisRequest;
  3083. NdisRequest->RequestType =
  3084. NdisRequestQueryInformation;
  3085. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  3086. OID_CO_TAPI_ADDRESS_CAPS;
  3087. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  3088. AddrCaps;
  3089. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  3090. EnumBufferSize;
  3091. Status =
  3092. NdisCoRequest(ClAdapter->ClBindingHandle,
  3093. pClAf->NdisAfHandle,
  3094. NULL,
  3095. NULL,
  3096. NdisRequest);
  3097. if (Status == NDIS_STATUS_PENDING){
  3098. Status = PxBlock(&pProxyRequest->Block);
  3099. }
  3100. if (Status != NDIS_STATUS_SUCCESS){
  3101. PxFreeMem(EnumBuffer);
  3102. return(NULL);
  3103. }
  3104. }else if (Status != STATUS_SUCCESS){
  3105. PxFreeMem(EnumBuffer);
  3106. return(NULL);
  3107. }
  3108. }
  3109. if (AddrCaps->LineAddressCaps.ulUsedSize < sizeof(LINE_ADDRESS_CAPS)) {
  3110. AddrCaps->LineAddressCaps.ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
  3111. }
  3112. SizeNeeded = sizeof(PX_TAPI_ADDR);
  3113. SizeNeeded += AddrCaps->LineAddressCaps.ulUsedSize;
  3114. SizeNeeded += sizeof(LINE_ADDRESS_STATUS);
  3115. SizeNeeded += 2*sizeof(PVOID);
  3116. PxAllocMem(TapiAddr, SizeNeeded, PX_TAPIADDR_TAG);
  3117. if (TapiAddr == NULL){
  3118. PxFreeMem(EnumBuffer);
  3119. return (NULL);
  3120. }
  3121. NdisZeroMemory((PUCHAR)TapiAddr, SizeNeeded);
  3122. TapiAddr->Caps = (PLINE_ADDRESS_CAPS)
  3123. ((PUCHAR)TapiAddr + sizeof(PX_TAPI_ADDR) + sizeof(PVOID));
  3124. (ULONG_PTR)TapiAddr->Caps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  3125. TapiAddr->AddrStatus = (PLINE_ADDRESS_STATUS)
  3126. ((PUCHAR)TapiAddr->Caps +
  3127. AddrCaps->LineAddressCaps.ulUsedSize + sizeof(PVOID));
  3128. (ULONG_PTR)TapiAddr->AddrStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  3129. NdisMoveMemory(TapiAddr->Caps,
  3130. &AddrCaps->LineAddressCaps,
  3131. AddrCaps->LineAddressCaps.ulUsedSize);
  3132. //
  3133. // Proxy fills some fields on behalf of all cm/miniports
  3134. //
  3135. ac = TapiAddr->Caps;
  3136. if (ac->ulTotalSize < ac->ulUsedSize) {
  3137. ac->ulTotalSize = ac->ulUsedSize;
  3138. }
  3139. if (ac->ulNeededSize < ac->ulNeededSize) {
  3140. ac->ulNeededSize = ac->ulUsedSize;
  3141. }
  3142. ac->ulLineDeviceID = TapiLine->ulDeviceID;
  3143. ac->ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
  3144. ac->ulAddressStates = LINEADDRESSSTATE_NUMCALLS;
  3145. ac->ulCallInfoStates = LINECALLINFOSTATE_BEARERMODE |
  3146. LINECALLINFOSTATE_RATE |
  3147. LINECALLINFOSTATE_MEDIAMODE;
  3148. ac->ulCallStates = LINECALLSTATE_IDLE |
  3149. LINECALLSTATE_OFFERING |
  3150. LINECALLSTATE_ACCEPTED |
  3151. LINECALLSTATE_BUSY |
  3152. LINECALLSTATE_CONNECTED |
  3153. LINECALLSTATE_PROCEEDING |
  3154. LINECALLSTATE_DISCONNECTED;
  3155. ac->ulDialToneModes = 0;
  3156. ac->ulBusyModes = LINEBUSYMODE_UNAVAIL;
  3157. ac->ulSpecialInfo = 0;
  3158. ac->ulDisconnectModes = LINEDISCONNECTMODE_NORMAL |
  3159. LINEDISCONNECTMODE_BUSY |
  3160. LINEDISCONNECTMODE_NOANSWER;
  3161. TapiAddr->TapiLine = TapiLine;
  3162. TapiAddr->AddrId = AddrID;
  3163. PxFreeMem(EnumBuffer);
  3164. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Allocated TapiAddr %p AddrId %d for TapiLine %p\n", TapiAddr, TapiAddr->AddrId, TapiLine));
  3165. return (TapiAddr);
  3166. }
  3167. VOID
  3168. FreeTapiAddr(
  3169. PPX_TAPI_ADDR TapiAddr
  3170. )
  3171. {
  3172. //
  3173. // ToDo! we need to tear down all
  3174. // active calls on this address.
  3175. //
  3176. PxFreeMem(TapiAddr);
  3177. }
  3178. NDIS_STATUS
  3179. AllocateTapiCallInfo(
  3180. PPX_VC pVc,
  3181. LINE_CALL_INFO UNALIGNED *LineCallInfo
  3182. )
  3183. {
  3184. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3185. ULONG SizeNeeded;
  3186. if (pVc->CallInfo) {
  3187. PxFreeMem(pVc->CallInfo);
  3188. }
  3189. if (LineCallInfo != NULL) {
  3190. SizeNeeded = LineCallInfo->ulUsedSize;
  3191. } else {
  3192. SizeNeeded = sizeof(LINE_CALL_INFO) + LINE_CALL_INFO_VAR_DATA_SIZE;
  3193. }
  3194. PxAllocMem(pVc->CallInfo, SizeNeeded, PX_LINECALLINFO_TAG);
  3195. if (pVc->CallInfo == NULL) {
  3196. return (NDIS_STATUS_RESOURCES);
  3197. }
  3198. pVc->ulCallInfoFieldsChanged = 0;
  3199. NdisZeroMemory(pVc->CallInfo, SizeNeeded);
  3200. if (LineCallInfo != NULL) {
  3201. NdisMoveMemory(pVc->CallInfo,
  3202. LineCallInfo,
  3203. LineCallInfo->ulUsedSize);
  3204. } else {
  3205. pVc->CallInfo->ulTotalSize = SizeNeeded;
  3206. pVc->CallInfo->ulNeededSize = SizeNeeded;
  3207. pVc->CallInfo->ulUsedSize = sizeof(LINE_CALL_INFO);
  3208. }
  3209. return (Status);
  3210. }
  3211. BOOLEAN
  3212. InsertVcInTable(
  3213. PPX_VC pVc
  3214. )
  3215. {
  3216. ULONG i;
  3217. ULONG index;
  3218. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3219. PUCHAR AllocatedMemory;
  3220. LOCK_STATE LockState;
  3221. PPX_CL_AF pClAf;
  3222. NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
  3223. if (VcTable.Count == VcTable.Size) {
  3224. ULONG SizeNeeded;
  3225. PUCHAR AllocatedMemory;
  3226. PPX_VC *NewTable;
  3227. //
  3228. // Grow the table
  3229. //
  3230. SizeNeeded =
  3231. (VcTable.Size + VcTable.Size/2) * sizeof(PPX_VC);
  3232. PxAllocMem(AllocatedMemory, SizeNeeded, PX_VCTABLE_TAG);
  3233. if (AllocatedMemory == NULL) {
  3234. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3235. return (FALSE);
  3236. }
  3237. RtlZeroMemory(AllocatedMemory,SizeNeeded);
  3238. NewTable = (PPX_VC*)AllocatedMemory;
  3239. RtlMoveMemory((PUCHAR)NewTable,
  3240. (PUCHAR)VcTable.Table,
  3241. (sizeof(PPX_VC) * VcTable.Size));
  3242. PxFreeMem(VcTable.Table);
  3243. VcTable.Table = NewTable;
  3244. VcTable.Size += VcTable.Size/2;
  3245. }
  3246. i = VcTable.Size;
  3247. index = VcTable.NextSlot;
  3248. do {
  3249. if (VcTable.Table[index] == NULL) {
  3250. NdisDprAcquireSpinLock(&pVc->Lock);
  3251. pVc->hdCall = index;
  3252. VcTable.Table[index] = pVc;
  3253. InsertTailList(&VcTable.List,
  3254. &pVc->Linkage);
  3255. VcTable.Count++;
  3256. VcTable.NextSlot =
  3257. (VcTable.NextSlot + 1) % VcTable.Size;
  3258. pVc->Flags |= PX_VC_IN_TABLE;
  3259. pClAf = pVc->ClAf;
  3260. NdisDprReleaseSpinLock(&pVc->Lock);
  3261. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Inserting pVc %x in VcTable hdCall %d\n", pVc, pVc->hdCall));
  3262. break;
  3263. }
  3264. index = (index+1) % VcTable.Size;
  3265. } while (--i);
  3266. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3267. if (i != 0) {
  3268. NdisAcquireSpinLock(&pClAf->Lock);
  3269. REF_CL_AF(pClAf);
  3270. InsertTailList(&pClAf->VcList, &pVc->ClAfLinkage);
  3271. NdisReleaseSpinLock(&pClAf->Lock);
  3272. } else {
  3273. PXDEBUGP(PXD_TAPI,PXM_TAPI, ("Failed to insert pVc %x in VcTable\n", pVc));
  3274. }
  3275. return (i != 0);
  3276. }
  3277. VOID
  3278. RemoveVcFromTable(
  3279. PPX_VC pVc
  3280. )
  3281. {
  3282. LOCK_STATE LockState;
  3283. PPX_CL_AF pClAf;
  3284. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Removing pVc %x from VcTable hdCall %d\n", pVc, pVc->hdCall));
  3285. NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
  3286. ASSERT(VcTable.Table[pVc->hdCall] == pVc);
  3287. VcTable.Table[pVc->hdCall] = NULL;
  3288. VcTable.Count--;
  3289. NdisDprAcquireSpinLock(&pVc->Lock);
  3290. RemoveEntryList(&pVc->Linkage);
  3291. pVc->Flags &= ~PX_VC_IN_TABLE;
  3292. pClAf = pVc->ClAf;
  3293. NdisDprReleaseSpinLock(&pVc->Lock);
  3294. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3295. NdisAcquireSpinLock(&pClAf->Lock);
  3296. RemoveEntryList(&pVc->ClAfLinkage);
  3297. DEREF_CL_AF_LOCKED(pClAf);
  3298. }
  3299. BOOLEAN
  3300. IsTapiLineValid(
  3301. ULONG hdLine,
  3302. PPX_TAPI_LINE *TapiLine
  3303. )
  3304. {
  3305. PPX_TAPI_LINE RetLine;
  3306. LOCK_STATE LockState;
  3307. ULONG i;
  3308. *TapiLine = NULL;
  3309. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  3310. for (i = 0; i < LineTable.Size; i++) {
  3311. PPX_TAPI_LINE RetLine;
  3312. RetLine = LineTable.Table[i];
  3313. if ((RetLine != NULL) &&
  3314. (RetLine->hdLine == hdLine)) {
  3315. *TapiLine = RetLine;
  3316. NdisDprAcquireSpinLock(&RetLine->Lock);
  3317. REF_TAPILINE(RetLine);
  3318. NdisDprReleaseSpinLock(&RetLine->Lock);
  3319. break;
  3320. }
  3321. }
  3322. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3323. return (*TapiLine != NULL);
  3324. }
  3325. BOOLEAN
  3326. IsTapiDeviceValid(
  3327. ULONG ulDeviceID,
  3328. PPX_TAPI_LINE *TapiLine
  3329. )
  3330. {
  3331. LOCK_STATE LockState;
  3332. ULONG i;
  3333. *TapiLine = NULL;
  3334. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  3335. for (i = 0; i < LineTable.Size; i++) {
  3336. PPX_TAPI_LINE RetLine;
  3337. RetLine = LineTable.Table[i];
  3338. if ((RetLine != NULL) &&
  3339. (RetLine->ulDeviceID == ulDeviceID)) {
  3340. *TapiLine = RetLine;
  3341. NdisDprAcquireSpinLock(&RetLine->Lock);
  3342. REF_TAPILINE(RetLine);
  3343. NdisDprReleaseSpinLock(&RetLine->Lock);
  3344. break;
  3345. }
  3346. }
  3347. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3348. return (*TapiLine != NULL);
  3349. }
  3350. BOOLEAN
  3351. IsVcValid(
  3352. ULONG_PTR CallId,
  3353. PPX_VC *pVc
  3354. )
  3355. {
  3356. PPX_VC RetVc = NULL;
  3357. LOCK_STATE LockState;
  3358. ULONG i;
  3359. NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
  3360. if (CallId < VcTable.Size) {
  3361. RetVc = VcTable.Table[CallId];
  3362. }
  3363. if (RetVc != NULL) {
  3364. NdisDprAcquireSpinLock(&RetVc->Lock);
  3365. REF_VC(RetVc);
  3366. NdisDprReleaseSpinLock(&RetVc->Lock);
  3367. }
  3368. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3369. *pVc = RetVc;
  3370. return (RetVc != NULL);
  3371. }
  3372. VOID
  3373. GetVcFromCtx(
  3374. NDIS_HANDLE VcCtx,
  3375. PPX_VC *pVc
  3376. )
  3377. {
  3378. PPX_VC RetVc = NULL;
  3379. ULONG_PTR i;
  3380. LOCK_STATE LockState;
  3381. NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
  3382. i = (ULONG_PTR)(VcCtx);
  3383. if (i < VcTable.Size) {
  3384. RetVc = VcTable.Table[i];
  3385. }
  3386. if (RetVc != NULL) {
  3387. NdisDprAcquireSpinLock(&RetVc->Lock);
  3388. REF_VC(RetVc);
  3389. NdisDprReleaseSpinLock(&RetVc->Lock);
  3390. }
  3391. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3392. *pVc = RetVc;
  3393. }
  3394. //
  3395. // Function assumes that the TapiLine's spinlock is held!
  3396. //
  3397. BOOLEAN
  3398. IsAddressValid(
  3399. PPX_TAPI_LINE TapiLine,
  3400. ULONG AddressId,
  3401. PPX_TAPI_ADDR *TapiAddr
  3402. )
  3403. {
  3404. PPX_TAPI_ADDR RetAddr = NULL;
  3405. do {
  3406. if (AddressId >= TapiLine->AddrTable.Count) {
  3407. break;
  3408. }
  3409. RetAddr = TapiLine->AddrTable.Table[AddressId];
  3410. } while (FALSE);
  3411. *TapiAddr = RetAddr;
  3412. return (RetAddr != NULL);
  3413. }
  3414. BOOLEAN
  3415. GetLineFromCmLineID(
  3416. PPX_TAPI_PROVIDER TapiProvider,
  3417. ULONG CmLineID,
  3418. PPX_TAPI_LINE *TapiLine
  3419. )
  3420. {
  3421. PPX_TAPI_LINE RetLine;
  3422. NdisAcquireSpinLock(&TapiProvider->Lock);
  3423. RetLine = (PPX_TAPI_LINE)
  3424. TapiProvider->LineList.Flink;
  3425. while ((PVOID)RetLine != (PVOID)&TapiProvider->LineList) {
  3426. if ((RetLine->CmLineID == CmLineID) &&
  3427. (RetLine->DevStatus->ulNumOpens != 0)) {
  3428. break;
  3429. }
  3430. RetLine = (PPX_TAPI_LINE)
  3431. RetLine->Linkage.Flink;
  3432. }
  3433. if ((PVOID)RetLine == (PVOID)&TapiProvider->LineList) {
  3434. RetLine = NULL;
  3435. }
  3436. NdisReleaseSpinLock(&TapiProvider->Lock);
  3437. *TapiLine = RetLine;
  3438. return (RetLine != NULL);
  3439. }
  3440. BOOLEAN
  3441. GetAvailLineFromProvider(
  3442. PPX_TAPI_PROVIDER TapiProvider,
  3443. PPX_TAPI_LINE *TapiLine,
  3444. PPX_TAPI_ADDR *TapiAddr
  3445. )
  3446. {
  3447. LOCK_STATE LockState;
  3448. ULONG i;
  3449. PPX_TAPI_LINE tl;
  3450. NdisAcquireSpinLock(&TapiProvider->Lock);
  3451. tl = (PPX_TAPI_LINE)TapiProvider->LineList.Flink;
  3452. while ((PVOID)tl != (PVOID)&TapiProvider->LineList) {
  3453. PTAPI_ADDR_TABLE AddrTable;
  3454. PPX_TAPI_ADDR ta;
  3455. NdisDprAcquireSpinLock(&tl->Lock);
  3456. if (tl->DevStatus->ulNumOpens != 0) {
  3457. AddrTable = &tl->AddrTable;
  3458. ta = (PPX_TAPI_ADDR)AddrTable->List.Flink;
  3459. //
  3460. // Walk the addresses on this line
  3461. //
  3462. while ((PVOID)ta != (PVOID)&AddrTable->List) {
  3463. //
  3464. // If this address has a callcount that is
  3465. // < then the max num it supports, add another
  3466. // call on this address!
  3467. //
  3468. if (ta->CallCount < ta->Caps->ulMaxNumActiveCalls) {
  3469. *TapiLine = tl;
  3470. *TapiAddr = ta;
  3471. NdisDprReleaseSpinLock(&tl->Lock);
  3472. NdisReleaseSpinLock(&TapiProvider->Lock);
  3473. return (TRUE);
  3474. }
  3475. ta = (PPX_TAPI_ADDR)ta->Linkage.Flink;
  3476. }
  3477. }
  3478. NdisDprReleaseSpinLock(&tl->Lock);
  3479. tl = (PPX_TAPI_LINE)tl->Linkage.Flink;
  3480. }
  3481. NdisReleaseSpinLock(&TapiProvider->Lock);
  3482. return (FALSE);
  3483. }
  3484. //
  3485. // Function assumes that the TapiLine's spinlock is held!
  3486. //
  3487. PPX_TAPI_ADDR
  3488. GetAvailAddrFromLine(
  3489. PPX_TAPI_LINE TapiLine
  3490. )
  3491. {
  3492. PPX_TAPI_ADDR TapiAddr;
  3493. PTAPI_ADDR_TABLE AddrTable;
  3494. AddrTable = &TapiLine->AddrTable;
  3495. TapiAddr = (PPX_TAPI_ADDR)AddrTable->List.Flink;
  3496. //
  3497. // Walk the addresses on this line
  3498. //
  3499. while ((PVOID)TapiAddr != (PVOID)&AddrTable->List) {
  3500. //
  3501. // If this address has a callcount that is
  3502. // < then the max num it supports, add another
  3503. // call on this address!
  3504. //
  3505. if (TapiAddr->CallCount <
  3506. TapiAddr->Caps->ulMaxNumActiveCalls) {
  3507. return (TapiAddr);
  3508. }
  3509. TapiAddr = (PPX_TAPI_ADDR)TapiAddr->Linkage.Flink;
  3510. }
  3511. return (NULL);
  3512. }
  3513. BOOLEAN
  3514. InsertLineInTable(
  3515. PPX_TAPI_LINE TapiLine
  3516. )
  3517. {
  3518. ULONG i;
  3519. ULONG index;
  3520. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3521. PUCHAR AllocatedMemory;
  3522. LOCK_STATE LockState;
  3523. NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
  3524. if (LineTable.Count == LineTable.Size) {
  3525. ULONG SizeNeeded;
  3526. PUCHAR AllocatedMemory;
  3527. PPX_TAPI_LINE *NewTable;
  3528. //
  3529. // Grow the table
  3530. //
  3531. SizeNeeded =
  3532. (LineTable.Size + LineTable.Size/2) * sizeof(PPX_TAPI_LINE);
  3533. PxAllocMem(AllocatedMemory, SizeNeeded, PX_LINETABLE_TAG);
  3534. if (AllocatedMemory == NULL) {
  3535. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3536. return (FALSE);
  3537. }
  3538. RtlZeroMemory(AllocatedMemory,SizeNeeded);
  3539. NewTable = (PPX_TAPI_LINE*)AllocatedMemory;
  3540. RtlMoveMemory((PUCHAR)NewTable,
  3541. (PUCHAR)LineTable.Table,
  3542. (sizeof(PPX_TAPI_LINE) * LineTable.Size));
  3543. PxFreeMem(LineTable.Table);
  3544. LineTable.Table = NewTable;
  3545. LineTable.Size += LineTable.Size/2;
  3546. }
  3547. i = LineTable.Size;
  3548. index = LineTable.NextSlot;
  3549. do {
  3550. if (LineTable.Table[index] == NULL) {
  3551. TapiLine->hdLine = index;
  3552. TapiLine->Flags |= PX_LINE_IN_TABLE;
  3553. LineTable.Table[index] = TapiLine;
  3554. LineTable.Count++;
  3555. LineTable.NextSlot =
  3556. (LineTable.NextSlot + 1) % LineTable.Size;
  3557. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  3558. ("Inserting TapiLine %p in LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
  3559. break;
  3560. }
  3561. index = (index+1) % LineTable.Size;
  3562. } while (--i);
  3563. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3564. #if DBG
  3565. if (i == 0) {
  3566. PXDEBUGP(PXD_TAPI,PXM_TAPI,
  3567. ("Failed to insert TapiLine %p in LineTable\n", TapiLine));
  3568. }
  3569. #endif
  3570. return (i != 0);
  3571. }
  3572. VOID
  3573. RemoveTapiLineFromTable(
  3574. PPX_TAPI_LINE TapiLine
  3575. )
  3576. {
  3577. LOCK_STATE LockState;
  3578. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  3579. ("Removing TapiLine %p from LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
  3580. NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
  3581. ASSERT(LineTable.Table[TapiLine->hdLine] == TapiLine);
  3582. LineTable.Table[TapiLine->hdLine] = NULL;
  3583. TapiLine->Flags &= ~PX_LINE_IN_TABLE;
  3584. LineTable.Count--;
  3585. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3586. }
  3587. NDIS_STATUS
  3588. PxVcCleanup(
  3589. PPX_VC pVc,
  3590. ULONG Flags
  3591. )
  3592. {
  3593. NDIS_STATUS Status;
  3594. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  3595. ("PxVcCleanup: Vc %p, State: %x, HandoffState: %x VcFlags: %x, NewFlags: %x\n",
  3596. pVc, pVc->State, pVc->HandoffState, Flags, pVc->Flags, Flags));
  3597. //
  3598. // Terminate Digit Gathering or Monitoring.
  3599. //
  3600. if (pVc->ulMonitorDigitsModes != 0) {
  3601. NdisReleaseSpinLock(&pVc->Lock);
  3602. PxStopDigitReporting(pVc);
  3603. NdisAcquireSpinLock(&pVc->Lock);
  3604. pVc->ulMonitorDigitsModes = 0;
  3605. } else if (pVc->PendingGatherDigits != NULL) {
  3606. PNDISTAPI_REQUEST pNdisTapiRequest = pVc->PendingGatherDigits;
  3607. pVc->PendingGatherDigits = NULL;
  3608. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
  3609. }
  3610. switch (pVc->State) {
  3611. case PX_VC_IDLE:
  3612. //
  3613. // Already idle do nothing.
  3614. //
  3615. Status = NDIS_STATUS_SUCCESS;
  3616. break;
  3617. case PX_VC_PROCEEDING:
  3618. //
  3619. // We have an outgoing call, when it completes close
  3620. // it down with ndis and complete the drop when
  3621. // in PxClCloseCallComplete.
  3622. //
  3623. pVc->PrevState = pVc->State;
  3624. pVc->State = PX_VC_DISCONNECTING;
  3625. //
  3626. // Attempt to close the call directly
  3627. // if this fails we will cleanup when
  3628. // the outgoing call completes
  3629. //
  3630. pVc->Flags |= (PX_VC_OUTCALL_ABORTING |
  3631. PX_VC_CLEANUP_CM |
  3632. Flags);
  3633. PxCloseCallWithCm(pVc);
  3634. Status = NDIS_STATUS_PENDING;
  3635. break;
  3636. case PX_VC_OFFERING:
  3637. //
  3638. // We have an incoming call offered to tapi. Close
  3639. // it down now by calling it's callcomplete handler
  3640. // with a non-success value.
  3641. //
  3642. pVc->Flags |= (Flags |
  3643. PX_VC_INCALL_ABORTING);
  3644. pVc->PrevState = pVc->State;
  3645. if (pVc->Flags & PX_VC_CLEANUP_CM) {
  3646. pVc->State= PX_VC_DISCONNECTING;
  3647. } else {
  3648. pVc->State = PX_VC_IDLE;
  3649. }
  3650. if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
  3651. PxStopIncomingCallTimeout(pVc);
  3652. }
  3653. NdisReleaseSpinLock(&pVc->Lock);
  3654. NdisClIncomingCallComplete(NDIS_STATUS_FAILURE,
  3655. pVc->ClVcHandle,
  3656. pVc->pCallParameters);
  3657. NdisAcquireSpinLock(&pVc->Lock);
  3658. if (pVc->Flags & PX_VC_CLEANUP_CM) {
  3659. PxCloseCallWithCm(pVc);
  3660. } else {
  3661. SendTapiCallState(pVc,
  3662. LINECALLSTATE_DISCONNECTED,
  3663. 0,
  3664. pVc->CallInfo->ulMediaMode);
  3665. //
  3666. // Remove the ref applied in PxClIncomingCall.
  3667. // Don't use the full deref code here as the
  3668. // ref applied when we mapped the vc will
  3669. // keep the vc around.
  3670. //
  3671. pVc->RefCount--;
  3672. }
  3673. Status = NDIS_STATUS_SUCCESS;
  3674. break;
  3675. case PX_VC_DISCONNECTING:
  3676. pVc->Flags |= (Flags);
  3677. Status = NDIS_STATUS_PENDING;
  3678. break;
  3679. case PX_VC_CONNECTED:
  3680. //
  3681. // We have a call that needs to be closed with ndis.
  3682. // This may include dropping the call with a client
  3683. // depending on the handoff state. Complete the drop
  3684. // irp in PxClCloseCallComplete
  3685. //
  3686. if (!(pVc->Flags & PX_VC_DROP_PENDING)) {
  3687. pVc->PrevState = pVc->State;
  3688. pVc->State = PX_VC_DISCONNECTING;
  3689. pVc->Flags |= (Flags | PX_VC_CLEANUP_CM);
  3690. Status =
  3691. PxCloseCallWithCl(pVc);
  3692. if (Status != NDIS_STATUS_PENDING) {
  3693. PxCloseCallWithCm(pVc);
  3694. }
  3695. }
  3696. Status = NDIS_STATUS_PENDING;
  3697. break;
  3698. default:
  3699. PXDEBUGP(PXD_FATAL, PXM_TAPI,
  3700. ("PxVcCleanup: Invalid VcState! Vc: %p VcState: %x CallState: %x\n",
  3701. pVc, pVc->State, pVc->ulCallState ));
  3702. Status = NDIS_STATUS_FAILURE;
  3703. ASSERT(0);
  3704. break;
  3705. }
  3706. return (Status);
  3707. }