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

5175 lines
138 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 = 0;
  286. WCHAR ProviderInfo[128];
  287. ULONG ProviderInfoSize = 0;
  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 dstTemp;
  322. NdisZeroMemory(LineName, sizeof(LineName));
  323. dstTemp = (PUCHAR)LineName;
  324. NdisMoveMemory(dstTemp,
  325. (PUCHAR)(ClAdapter->MediaName),
  326. ClAdapter->MediaNameLength);
  327. (ULONG_PTR)dstTemp += ClAdapter->MediaNameLength;
  328. //
  329. // ToDo! Shoud get the name of the adapter
  330. // and insert here!
  331. //
  332. NdisMoveMemory(dstTemp,
  333. L" - Line",
  334. wcslen(L" - Line") * sizeof(WCHAR));
  335. (ULONG_PTR)dstTemp +=
  336. wcslen(L" - Line") * sizeof(WCHAR);
  337. (VOID)
  338. IntegerToWChar(TapiLine->CmLineID,
  339. -4,
  340. (WCHAR *)dstTemp);
  341. (ULONG_PTR)dstTemp += 4 * sizeof(WCHAR);
  342. LineNameSize = (ULONG)((ULONG_PTR)dstTemp - (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. if(pVc->CloseFlags & PX_VC_TAPI_DROP)
  962. {
  963. DEREF_VC_LOCKED(pVc);
  964. return (NDIS_STATUS_SUCCESS);
  965. }
  966. Irp = pNdisTapiRequest->Irp;
  967. IoSetCancelRoutine(Irp, PxCancelSetQuery);
  968. //
  969. // Insert the request in the Vc's pending list
  970. //
  971. InsertTailList(&pVc->PendingDropReqs,
  972. &pNdisTapiRequest->Linkage);
  973. pVc->CloseFlags |= PX_VC_TAPI_DROP;
  974. //
  975. // Check the Vc state and act accordingly
  976. //
  977. Status =
  978. PxVcCleanup(pVc, PX_VC_DROP_PENDING);
  979. if (Status != NDIS_STATUS_PENDING) {
  980. RemoveEntryList(&pNdisTapiRequest->Linkage);
  981. IoSetCancelRoutine(Irp, NULL);
  982. }
  983. //
  984. // Deref for ref applied at entry when
  985. // validating the vc
  986. //
  987. DEREF_VC_LOCKED(pVc);
  988. return (Status);
  989. }
  990. NDIS_STATUS
  991. PxTapiGetAddressCaps(
  992. IN PNDISTAPI_REQUEST pNdisTapiRequest
  993. )
  994. /*++
  995. Routine Description:
  996. Placeholder for TAPI OID action routines
  997. Arguments:
  998. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  999. Return Value:
  1000. --*/
  1001. {
  1002. PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps =
  1003. (PNDIS_TAPI_GET_ADDRESS_CAPS) pNdisTapiRequest->Data;
  1004. PPX_TAPI_LINE TapiLine;
  1005. PPX_TAPI_ADDR TapiAddr;
  1006. PPX_ADAPTER ClAdapter;
  1007. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1008. if (!IsTapiDeviceValid(pNdisTapiRequest->ulDeviceID, &TapiLine)) {
  1009. PXDEBUGP (PXD_WARNING, PXM_TAPI, ( "PxTapiGetAddressCaps: NDISTAPIERR_BADDEVICEID: line = %x\n", pNdisTapiRequest->ulDeviceID));
  1010. return (NDISTAPIERR_BADDEVICEID);
  1011. }
  1012. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  1013. ("PxTapiGetAddressCaps: got device %p from ID %d\n",
  1014. TapiLine, pNdisTapiRequest->ulDeviceID));
  1015. NdisAcquireSpinLock(&TapiLine->Lock);
  1016. do {
  1017. ULONG DevClassesSize = 0;
  1018. USHORT DevClassesList[512];
  1019. ULONG SizeToMove;
  1020. ULONG TotalSize;
  1021. ULONG SizeLeft;
  1022. PLINE_ADDRESS_CAPS In, Out;
  1023. //
  1024. // Get the tapi address that we are interested in
  1025. //
  1026. if (!IsAddressValid(TapiLine,
  1027. pNdisTapiGetAddressCaps->ulAddressID,
  1028. &TapiAddr)) {
  1029. Status = NDIS_STATUS_TAPI_INVALADDRESSID;
  1030. break;
  1031. }
  1032. In = TapiAddr->Caps;
  1033. Out = &pNdisTapiGetAddressCaps->LineAddressCaps;
  1034. //
  1035. // Add some space for our device classes
  1036. //
  1037. DevClassesSize = sizeof(DevClassesList);
  1038. NdisZeroMemory((PUCHAR)DevClassesList,
  1039. sizeof(DevClassesList));
  1040. if (TapiLine->TapiProvider->Adapter != NULL) {
  1041. GetAllDevClasses(TapiLine->TapiProvider->Adapter,
  1042. DevClassesList,
  1043. &DevClassesSize);
  1044. }
  1045. //
  1046. // Synchronously get Address caps for this device
  1047. //
  1048. SizeToMove = (In->ulUsedSize > Out->ulTotalSize) ?
  1049. Out->ulTotalSize : In->ulUsedSize;
  1050. TotalSize = Out->ulTotalSize;
  1051. NdisMoveMemory((PUCHAR)Out, (PUCHAR)In, SizeToMove);
  1052. SizeLeft =
  1053. TotalSize - SizeToMove;
  1054. Out->ulTotalSize = TotalSize;
  1055. Out->ulUsedSize = SizeToMove;
  1056. Out->ulNeededSize =
  1057. In->ulUsedSize + DevClassesSize;
  1058. if (SizeLeft > 0) {
  1059. //
  1060. // If these is room fill in our devclasses
  1061. //
  1062. if (DevClassesSize > 0) {
  1063. PUCHAR dst;
  1064. dst = (PUCHAR)Out + Out->ulUsedSize;
  1065. SizeToMove = (SizeLeft > DevClassesSize) ?
  1066. DevClassesSize : SizeLeft;
  1067. NdisMoveMemory(dst, DevClassesList, SizeToMove);
  1068. Out->ulDeviceClassesSize = SizeToMove;
  1069. Out->ulDeviceClassesOffset =
  1070. (ULONG)((ULONG_PTR)dst - (ULONG_PTR)Out);
  1071. Out->ulUsedSize += SizeToMove;
  1072. SizeLeft -= SizeToMove;
  1073. }
  1074. }
  1075. } while (FALSE);
  1076. DEREF_TAPILINE_LOCKED(TapiLine);
  1077. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetAddressCaps: exit. \n"));
  1078. return (Status);
  1079. }
  1080. NDIS_STATUS
  1081. PxTapiGetAddressID(
  1082. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. Placeholder for TAPI OID action routines
  1087. Arguments:
  1088. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1089. Return Value:
  1090. --*/
  1091. {
  1092. PNDIS_TAPI_GET_ADDRESS_ID TapiBuffer =
  1093. (PNDIS_TAPI_GET_ADDRESS_ID) pNdisTapiRequest->Data;
  1094. PPX_TAPI_LINE TapiLine;
  1095. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: enter\n"));
  1096. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  1097. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetAddressID: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
  1098. return(NDISTAPIERR_BADDEVICEID);
  1099. }
  1100. NdisAcquireSpinLock(&TapiLine->Lock);
  1101. //
  1102. // ToDo!
  1103. //
  1104. TapiBuffer->ulAddressID = 0;
  1105. DEREF_TAPILINE_LOCKED(TapiLine);
  1106. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: exit\n"));
  1107. return (NDIS_STATUS_SUCCESS);
  1108. }
  1109. NDIS_STATUS
  1110. PxTapiGetAddressStatus(
  1111. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. Placeholder for TAPI OID action routines
  1116. Arguments:
  1117. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1118. Return Value:
  1119. --*/
  1120. {
  1121. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: enter\n"));
  1122. //
  1123. // ToDo!
  1124. //
  1125. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: exit\n"));
  1126. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1127. }
  1128. NDIS_STATUS
  1129. PxTapiGetCallAddressID(
  1130. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1131. )
  1132. /*++
  1133. Routine Description:
  1134. TAPI OID action routine
  1135. Arguments:
  1136. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1137. Return Value:
  1138. --*/
  1139. {
  1140. PNDIS_TAPI_GET_CALL_ADDRESS_ID TapiBuffer =
  1141. (PNDIS_TAPI_GET_CALL_ADDRESS_ID)pNdisTapiRequest->Data;
  1142. PPX_VC pVc;
  1143. if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
  1144. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallAddressID: invalid call handle %d\n",
  1145. TapiBuffer->hdCall));
  1146. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1147. }
  1148. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: Vc: %p\n", pVc));
  1149. NdisAcquireSpinLock(&pVc->Lock);
  1150. TapiBuffer->ulAddressID = pVc->TapiAddr->AddrId;
  1151. DEREF_VC_LOCKED(pVc);
  1152. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: exit\n"));
  1153. return (NDIS_STATUS_SUCCESS);
  1154. }
  1155. NDIS_STATUS
  1156. PxTapiGetCallInfo(
  1157. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1158. )
  1159. /*++
  1160. Routine Description:
  1161. TAPI OID action routine
  1162. Arguments:
  1163. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1164. Return Value:
  1165. --*/
  1166. {
  1167. PNDIS_TAPI_GET_CALL_INFO TapiBuffer =
  1168. (PNDIS_TAPI_GET_CALL_INFO)pNdisTapiRequest->Data;
  1169. PPX_VC pVc;
  1170. PPX_TAPI_LINE TapiLine;
  1171. LINE_CALL_INFO* CallInfo;
  1172. LINE_CALL_INFO* OutCallInfo = &TapiBuffer->LineCallInfo;
  1173. ULONG VarDataSize = 0; // Total available
  1174. ULONG VarDataUsed = 0;
  1175. if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
  1176. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallInfo: invalid call handle %d\n",
  1177. TapiBuffer->hdCall));
  1178. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1179. }
  1180. NdisAcquireSpinLock(&pVc->Lock);
  1181. //
  1182. // Make sure we have enough space to copy everything over
  1183. //
  1184. CallInfo = pVc->CallInfo;
  1185. TapiLine = pVc->TapiLine;
  1186. VarDataSize =
  1187. pNdisTapiRequest->ulDataSize - sizeof(NDIS_TAPI_GET_CALL_INFO);
  1188. PXDEBUGP (PXD_TAPI, PXM_TAPI,
  1189. ("PxTapiGetCallInfo: enter. pVc = %p, AvailSize = %x, needed = %x\n",
  1190. pVc, OutCallInfo->ulTotalSize, CallInfo->ulUsedSize));
  1191. OutCallInfo->ulNeededSize = CallInfo->ulUsedSize;
  1192. //
  1193. // Patch up the Id here. We store it in our callinfo
  1194. // block in terms of the call managers 0 based Id. We
  1195. // need to give tapi the Id it is looking for which is
  1196. // stored in the tapiline.
  1197. //
  1198. OutCallInfo->ulLineDeviceID = TapiLine->ulDeviceID;
  1199. OutCallInfo->ulAddressID = CallInfo->ulAddressID;
  1200. OutCallInfo->ulBearerMode = CallInfo->ulBearerMode;
  1201. OutCallInfo->ulRate = CallInfo->ulRate;
  1202. OutCallInfo->ulMediaMode = CallInfo->ulMediaMode;
  1203. OutCallInfo->ulAppSpecific = CallInfo->ulAppSpecific;
  1204. OutCallInfo->ulCallID = 0;
  1205. OutCallInfo->ulRelatedCallID = 0;
  1206. OutCallInfo->ulCallParamFlags = 0;
  1207. OutCallInfo->DialParams.ulDialPause = 0;
  1208. OutCallInfo->DialParams.ulDialSpeed = 0;
  1209. OutCallInfo->DialParams.ulDigitDuration = 0;
  1210. OutCallInfo->DialParams.ulWaitForDialtone = 0;
  1211. OutCallInfo->ulReason = CallInfo->ulReason;
  1212. OutCallInfo->ulCompletionID = 0;
  1213. OutCallInfo->ulCountryCode = 0;
  1214. OutCallInfo->ulTrunk = (ULONG)-1;
  1215. //
  1216. // Do the CallerID
  1217. //
  1218. if (CallInfo->ulCallerIDSize) {
  1219. if (((VarDataUsed + CallInfo->ulCallerIDSize) <= VarDataSize) &&
  1220. ((CallInfo->ulCallerIDOffset + CallInfo->ulCallerIDSize) <= CallInfo->ulUsedSize)) {
  1221. OutCallInfo->ulCallerIDSize = CallInfo->ulCallerIDSize;
  1222. OutCallInfo->ulCallerIDFlags = CallInfo->ulCallerIDFlags;
  1223. OutCallInfo->ulCallerIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
  1224. NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCallerIDOffset,
  1225. (PUCHAR)(CallInfo)+CallInfo->ulCallerIDOffset,
  1226. CallInfo->ulCallerIDSize);
  1227. VarDataUsed += CallInfo->ulCallerIDSize;
  1228. pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLERID;
  1229. }
  1230. } else {
  1231. OutCallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL;
  1232. OutCallInfo->ulCallerIDSize = 0;
  1233. OutCallInfo->ulCallerIDOffset = 0;
  1234. }
  1235. OutCallInfo->ulCallerIDNameSize = 0;
  1236. OutCallInfo->ulCallerIDNameOffset = 0;
  1237. //
  1238. // Do the CalledID
  1239. //
  1240. if (CallInfo->ulCalledIDSize) {
  1241. if (((VarDataUsed + CallInfo->ulCalledIDSize) <= VarDataSize) &&
  1242. ((CallInfo->ulCalledIDOffset + CallInfo->ulCalledIDSize) <= CallInfo->ulUsedSize)) {
  1243. OutCallInfo->ulCalledIDFlags = CallInfo->ulCalledIDFlags;
  1244. OutCallInfo->ulCalledIDSize = CallInfo->ulCalledIDSize;
  1245. OutCallInfo->ulCalledIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
  1246. NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCalledIDOffset,
  1247. (PUCHAR)(CallInfo)+CallInfo->ulCalledIDOffset,
  1248. CallInfo->ulCalledIDSize);
  1249. VarDataUsed += CallInfo->ulCalledIDSize;
  1250. pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLEDID;
  1251. }
  1252. } else {
  1253. OutCallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL;
  1254. OutCallInfo->ulCalledIDSize = 0;
  1255. OutCallInfo->ulCalledIDOffset = 0;
  1256. }
  1257. OutCallInfo->ulCalledIDNameSize = 0;
  1258. OutCallInfo->ulCalledIDNameOffset = 0;
  1259. OutCallInfo->ulCallStates = LINECALLSTATE_IDLE |
  1260. LINECALLSTATE_OFFERING |
  1261. LINECALLSTATE_CONNECTED |
  1262. LINECALLSTATE_PROCEEDING |
  1263. LINECALLSTATE_DISCONNECTED |
  1264. LINECALLSTATE_SPECIALINFO |
  1265. LINECALLSTATE_UNKNOWN;
  1266. OutCallInfo->ulOrigin = (pVc->Flags & PX_VC_OWNER) ? LINECALLORIGIN_EXTERNAL : LINECALLORIGIN_OUTBOUND;
  1267. OutCallInfo->ulReason = LINECALLREASON_UNAVAIL;
  1268. OutCallInfo->ulCompletionID = 0;
  1269. OutCallInfo->ulConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
  1270. OutCallInfo->ulConnectedIDSize = 0;
  1271. OutCallInfo->ulConnectedIDOffset = 0;
  1272. OutCallInfo->ulConnectedIDNameSize = 0;
  1273. OutCallInfo->ulConnectedIDNameOffset = 0;
  1274. OutCallInfo->ulRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
  1275. OutCallInfo->ulRedirectionIDSize = 0;
  1276. OutCallInfo->ulRedirectionIDOffset = 0;
  1277. OutCallInfo->ulRedirectionIDNameSize = 0;
  1278. OutCallInfo->ulRedirectionIDNameOffset = 0;
  1279. OutCallInfo->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  1280. OutCallInfo->ulRedirectingIDSize = 0;
  1281. OutCallInfo->ulRedirectingIDOffset = 0;
  1282. OutCallInfo->ulRedirectingIDNameSize = 0;
  1283. OutCallInfo->ulRedirectingIDNameOffset = 0;
  1284. OutCallInfo->ulDisplaySize = 0;
  1285. OutCallInfo->ulDisplayOffset = 0;
  1286. OutCallInfo->ulUserUserInfoSize = 0;
  1287. OutCallInfo->ulUserUserInfoOffset = 0;
  1288. OutCallInfo->ulHighLevelCompSize = 0;
  1289. OutCallInfo->ulHighLevelCompOffset = 0;
  1290. OutCallInfo->ulLowLevelCompSize = 0;
  1291. OutCallInfo->ulLowLevelCompOffset = 0;
  1292. OutCallInfo->ulChargingInfoSize = 0;
  1293. OutCallInfo->ulChargingInfoOffset = 0;
  1294. OutCallInfo->ulTerminalModesSize = 0;
  1295. OutCallInfo->ulTerminalModesOffset = 0;
  1296. OutCallInfo->ulDevSpecificSize = 0;
  1297. OutCallInfo->ulDevSpecificOffset = 0;
  1298. OutCallInfo->ulNeededSize =
  1299. OutCallInfo->ulUsedSize = sizeof(LINE_CALL_INFO) + VarDataUsed;
  1300. //
  1301. // Deref for ref applied at entry when
  1302. // validating the vc
  1303. //
  1304. DEREF_VC_LOCKED(pVc);
  1305. return (NDIS_STATUS_SUCCESS);
  1306. }
  1307. NDIS_STATUS
  1308. PxTapiGetCallStatus (
  1309. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. TAPI OID action routine
  1314. Arguments:
  1315. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1316. Return Value:
  1317. --*/
  1318. {
  1319. PNDIS_TAPI_GET_CALL_STATUS TapiBuffer =
  1320. (PNDIS_TAPI_GET_CALL_STATUS)pNdisTapiRequest->Data;
  1321. PPX_VC pVc;
  1322. LINE_CALL_INFO* CallInfo;
  1323. LINE_CALL_STATUS* CallStatus = &TapiBuffer->LineCallStatus;
  1324. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallStatus: enter\n"));\
  1325. if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
  1326. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallStatus: invalid call handle %d\n",
  1327. TapiBuffer->hdCall));
  1328. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1329. }
  1330. NdisAcquireSpinLock(&pVc->Lock);
  1331. CallInfo = pVc->CallInfo;
  1332. CallStatus->ulUsedSize = sizeof(LINE_CALL_STATUS);
  1333. CallStatus->ulCallState = pVc->ulCallState;
  1334. //
  1335. // fill the mode depending on the call state
  1336. //
  1337. switch (pVc->ulCallState) {
  1338. case LINECALLSTATE_IDLE:
  1339. default:
  1340. CallStatus->ulCallStateMode = 0;
  1341. CallStatus->ulCallFeatures = 0;
  1342. break;
  1343. case LINECALLSTATE_CONNECTED:
  1344. CallStatus->ulCallStateMode = 0;
  1345. CallStatus->ulCallFeatures = LINECALLFEATURE_DROP;
  1346. break;
  1347. case LINECALLSTATE_OFFERING:
  1348. CallStatus->ulCallStateMode = 0;
  1349. CallStatus->ulCallFeatures = LINECALLFEATURE_ANSWER;
  1350. break;
  1351. case LINECALLSTATE_DISCONNECTED:
  1352. if (pVc->ulCallStateMode == 0x11 )
  1353. CallStatus->ulCallStateMode = LINEDISCONNECTMODE_BUSY;
  1354. else
  1355. CallStatus->ulCallStateMode = LINEDISCONNECTMODE_NOANSWER;
  1356. break;
  1357. case LINECALLSTATE_BUSY:
  1358. CallStatus->ulCallStateMode = LINEBUSYMODE_UNAVAIL;
  1359. break;
  1360. case LINECALLSTATE_SPECIALINFO:
  1361. // if(cm->NoActiveLine)
  1362. // CallStatus->ulCallStateMode = LINESPECIALINFO_NOCIRCUIT;
  1363. CallStatus->ulCallStateMode = 0;
  1364. break;
  1365. }
  1366. CallStatus->ulDevSpecificSize = 0;
  1367. CallStatus->ulDevSpecificOffset = 0;
  1368. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("GetCallStatus: VC %x/%x, CallSt %x, Mode %x, Features %x\n",
  1369. pVc, pVc->Flags,
  1370. CallStatus->ulCallState,
  1371. CallStatus->ulCallStateMode,
  1372. CallStatus->ulCallFeatures));
  1373. //
  1374. // Deref for ref applied at entry when
  1375. // validating the vc
  1376. //
  1377. DEREF_VC_LOCKED(pVc);
  1378. return (NDIS_STATUS_SUCCESS);
  1379. }
  1380. NDIS_STATUS
  1381. PxTapiGetDevConfig(
  1382. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1383. )
  1384. /*++
  1385. Routine Description:
  1386. TAPI OID action routine
  1387. Arguments:
  1388. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1389. Return Value:
  1390. --*/
  1391. {
  1392. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: enter\n"));
  1393. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: exit\n"));
  1394. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1395. }
  1396. NDIS_STATUS
  1397. PxTapiGetExtensionID(
  1398. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1399. )
  1400. /*++
  1401. Routine Description:
  1402. TAPI OID action routine
  1403. Arguments:
  1404. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1405. Return Value:
  1406. --*/
  1407. {
  1408. PNDIS_TAPI_GET_EXTENSION_ID TapiBuffer = (PNDIS_TAPI_GET_EXTENSION_ID)pNdisTapiRequest->Data;
  1409. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: enter\n"));
  1410. // TapiBuffer->LineExtensionID.ulExtensionID0 = 0;
  1411. // TapiBuffer->LineExtensionID.ulExtensionID1 = 0;
  1412. // TapiBuffer->LineExtensionID.ulExtensionID2 = 0;
  1413. // TapiBuffer->LineExtensionID.ulExtensionID3 = 0;
  1414. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: exit\n"));
  1415. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1416. }
  1417. NDIS_STATUS
  1418. PxTapiGetLineDevStatus(
  1419. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1420. )
  1421. /*++
  1422. Routine Description:
  1423. TAPI OID action routine
  1424. Arguments:
  1425. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1426. Return Value:
  1427. --*/
  1428. {
  1429. PNDIS_TAPI_GET_LINE_DEV_STATUS TapiBuffer =
  1430. (PNDIS_TAPI_GET_LINE_DEV_STATUS)pNdisTapiRequest->Data;
  1431. PPX_TAPI_LINE TapiLine;
  1432. PX_ADAPTER *pAdapter;
  1433. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: enter\n"));
  1434. //
  1435. // validate line handle and get line pointer
  1436. //
  1437. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  1438. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
  1439. return (NDISTAPIERR_BADDEVICEID);
  1440. }
  1441. NdisAcquireSpinLock(&TapiLine->Lock);
  1442. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: got device %p from ID %d\n", TapiLine, TapiBuffer->hdLine));
  1443. //
  1444. // Get MediaModes and Current Calls
  1445. //
  1446. TapiBuffer->LineDevStatus.ulOpenMediaModes =
  1447. TapiLine->DevStatus->ulOpenMediaModes;
  1448. TapiBuffer->LineDevStatus.ulNumActiveCalls =
  1449. TapiLine->DevStatus->ulNumActiveCalls;
  1450. TapiBuffer->LineDevStatus.ulDevStatusFlags =
  1451. TapiLine->DevStatus->ulDevStatusFlags;
  1452. DEREF_TAPILINE_LOCKED(TapiLine);
  1453. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: exit\n"));
  1454. return (NDIS_STATUS_SUCCESS);
  1455. }
  1456. NDIS_STATUS
  1457. PxTapiNegotiateExtVersion(
  1458. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. TAPI OID action routine
  1463. Arguments:
  1464. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1465. Return Value:
  1466. --*/
  1467. {
  1468. PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion =
  1469. (PNDIS_TAPI_NEGOTIATE_EXT_VERSION) pNdisTapiRequest->Data;
  1470. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: enter\n"));
  1471. pNdisTapiNegotiateExtVersion->ulExtVersion = 0;
  1472. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: exit NDIS_STATUS_TAPI_OPERATIONUNAVAIL\n"));
  1473. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1474. }
  1475. NDIS_STATUS
  1476. PxTapiSendUserUserInfo(
  1477. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. TAPI OID action routine
  1482. Arguments:
  1483. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1484. Return Value:
  1485. --*/
  1486. {
  1487. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: enter\n"));
  1488. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: exit\n"));
  1489. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1490. }
  1491. NDIS_STATUS
  1492. PxTapiSetAppSpecific(
  1493. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1494. )
  1495. /*++
  1496. Routine Description:
  1497. TAPI OID action routine
  1498. Arguments:
  1499. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1500. Return Value:
  1501. --*/
  1502. {
  1503. PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific =
  1504. (PNDIS_TAPI_SET_APP_SPECIFIC)(pNdisTapiRequest->Data);
  1505. PPX_VC pVc;
  1506. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: enter\n"));
  1507. if (!IsVcValid(pNdisTapiSetAppSpecific->hdCall, &pVc)) {
  1508. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetAppSpecific: pVc invalid call handle %d\n",
  1509. pNdisTapiSetAppSpecific->hdCall));
  1510. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1511. }
  1512. NdisAcquireSpinLock(&pVc->Lock);
  1513. //
  1514. // Get the VC, and re-set the app specific longword.
  1515. //
  1516. pVc->CallInfo->ulAppSpecific =
  1517. pNdisTapiSetAppSpecific->ulAppSpecific;
  1518. //
  1519. // Deref for ref applied at entry when
  1520. // validating the vc
  1521. //
  1522. DEREF_VC_LOCKED(pVc);
  1523. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: exit\n"));
  1524. return (NDIS_STATUS_SUCCESS);
  1525. }
  1526. NDIS_STATUS
  1527. PxTapiSetCallParams(
  1528. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. TAPI OID action routine
  1533. Arguments:
  1534. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1535. Return Value:
  1536. --*/
  1537. {
  1538. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: enter\n"));
  1539. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: exit\n"));
  1540. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1541. }
  1542. NDIS_STATUS
  1543. PxTapiSetDefaultMediaDetection(
  1544. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1545. )
  1546. /*++
  1547. Routine Description:
  1548. TAPI OID action routine
  1549. Arguments:
  1550. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1551. Return Value:
  1552. --*/
  1553. {
  1554. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION TapiBuffer =
  1555. (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)pNdisTapiRequest->Data;
  1556. PPX_CL_AF pClAf = NULL;
  1557. PPX_CL_SAP pClSap = NULL;
  1558. PCO_SAP pCoSap;
  1559. PPX_TAPI_LINE TapiLine = NULL;
  1560. NDIS_STATUS Status;
  1561. BOOLEAN Found = FALSE;
  1562. PPX_TAPI_PROVIDER TapiProvider;
  1563. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: enter\n"));
  1564. //
  1565. // validate line handle and get line pointer
  1566. //
  1567. if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
  1568. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1569. ("PxTapiSetDefaultMediaDetection: NDISTAPIERR_BADDEVICEID: line = %x\n",
  1570. TapiBuffer->hdLine));
  1571. return (NDISTAPIERR_BADDEVICEID);
  1572. }
  1573. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  1574. ("PxTapiSetDefaultMediaDetection: got TapiLine %p from ID %d\n",
  1575. TapiLine, TapiBuffer->hdLine));
  1576. NdisAcquireSpinLock(&TapiLine->Lock);
  1577. do {
  1578. //
  1579. // Is this line in service? (does it have an valid af?)
  1580. //
  1581. if (!(TapiLine->DevStatus->ulDevStatusFlags &
  1582. LINEDEVSTATUSFLAGS_INSERVICE)) {
  1583. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1584. ("PxTapiSetDefaultMediaDetection: Line not in service!\n"));
  1585. NdisReleaseSpinLock(&TapiLine->Lock);
  1586. Status = NDIS_STATUS_TAPI_INVALLINESTATE;
  1587. break;
  1588. }
  1589. //
  1590. // Make sure this line supports these media modes
  1591. //
  1592. if ((TapiBuffer->ulMediaModes & TapiLine->DevCaps->ulMediaModes) !=
  1593. TapiBuffer->ulMediaModes) {
  1594. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1595. ("PxTapiSetDefaultMediaDetection: invalid media mode\n"));
  1596. NdisReleaseSpinLock(&TapiLine->Lock);
  1597. Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
  1598. break;
  1599. }
  1600. //
  1601. // See if we already have these media modes open
  1602. //
  1603. if ((TapiBuffer->ulMediaModes &
  1604. ~TapiLine->DevStatus->ulOpenMediaModes) == 0) {
  1605. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1606. ("PxTapiSetDefaultMediaDetection: Already have a sap!\n"));
  1607. NdisReleaseSpinLock(&TapiLine->Lock);
  1608. Status = NDIS_STATUS_SUCCESS;
  1609. break;
  1610. }
  1611. TapiLine->DevStatus->ulOpenMediaModes |=
  1612. TapiBuffer->ulMediaModes;
  1613. pClAf = TapiLine->ClAf;
  1614. pClSap = TapiLine->ClSap;
  1615. TapiLine->ClSap = NULL;
  1616. NdisReleaseSpinLock(&TapiLine->Lock);
  1617. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  1618. ("PxTapiSetDefaultMediaDetection: TapiLine: %p, pClAf: %p, MediaModes: %x\n",
  1619. TapiLine, pClAf, TapiLine->DevStatus->ulOpenMediaModes));
  1620. NdisAcquireSpinLock(&pClAf->Lock);
  1621. REF_CL_AF(pClAf);
  1622. if (pClSap != NULL) {
  1623. //
  1624. // We already have a sap on this line. We only need one
  1625. // per line so let's deregister the old one before registering
  1626. // the new one.
  1627. //
  1628. RemoveEntryList(&pClSap->Linkage);
  1629. InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
  1630. NdisReleaseSpinLock(&pClAf->Lock);
  1631. InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
  1632. Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
  1633. if (Status != NDIS_STATUS_PENDING) {
  1634. PxClDeregisterSapComplete(Status, pClSap);
  1635. }
  1636. } else {
  1637. NdisReleaseSpinLock(&pClAf->Lock);
  1638. }
  1639. //
  1640. // Get a SAP translation for this Media Mode setting.
  1641. // The function is called with the Af lock held and
  1642. // returns with the Af lock released!
  1643. //
  1644. pClSap = (*pClAf->AfGetNdisSap)(pClAf, TapiLine);
  1645. if (pClSap == NULL) {
  1646. Status = NDIS_STATUS_RESOURCES;
  1647. break;
  1648. }
  1649. NdisAcquireSpinLock(&pClAf->Lock);
  1650. InsertTailList(&pClAf->ClSapList, &pClSap->Linkage);
  1651. REF_CL_AF(pClAf);
  1652. NdisReleaseSpinLock(&pClAf->Lock);
  1653. //
  1654. // Register the new sap
  1655. //
  1656. Status = NdisClRegisterSap(pClAf->NdisAfHandle,
  1657. pClSap,
  1658. pClSap->CoSap,
  1659. &pClSap->NdisSapHandle);
  1660. if (Status != NDIS_STATUS_PENDING) {
  1661. PxClRegisterSapComplete(Status,
  1662. pClSap,
  1663. pClSap->CoSap,
  1664. pClSap->NdisSapHandle);
  1665. }
  1666. } while (FALSE);
  1667. DEREF_CL_AF(pClAf);
  1668. DEREF_TAPILINE(TapiLine);
  1669. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: exit\n"));
  1670. return (NDIS_STATUS_SUCCESS);
  1671. }
  1672. NDIS_STATUS
  1673. PxTapiSetDevConfig(
  1674. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1675. )
  1676. /*++
  1677. Routine Description:
  1678. TAPI OID action routine
  1679. Arguments:
  1680. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1681. Return Value:
  1682. --*/
  1683. {
  1684. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: enter\n"));
  1685. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: exit\n"));
  1686. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1687. }
  1688. NDIS_STATUS
  1689. PxTapiSetMediaMode(
  1690. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. TAPI OID action routine
  1695. Arguments:
  1696. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1697. Return Value:
  1698. --*/
  1699. {
  1700. PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode =
  1701. (PNDIS_TAPI_SET_MEDIA_MODE)(pNdisTapiRequest->Data);
  1702. PPX_VC pVc;
  1703. PPX_TAPI_LINE TapiLine;
  1704. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1705. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: enter\n"));
  1706. if (!IsVcValid(pNdisTapiSetMediaMode->hdCall, &pVc)) {
  1707. PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetMediaMode: pVc invalid call handle %d\n",
  1708. pNdisTapiSetMediaMode->hdCall));
  1709. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  1710. }
  1711. NdisAcquireSpinLock(&pVc->Lock);
  1712. TapiLine = pVc->TapiAddr->TapiLine;
  1713. if ((TapiLine->DevCaps->ulMediaModes & pNdisTapiSetMediaMode->ulMediaMode)) {
  1714. pVc->CallInfo->ulMediaMode = pNdisTapiSetMediaMode->ulMediaMode;
  1715. } else {
  1716. Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
  1717. }
  1718. //
  1719. // Deref for ref applied at entry when
  1720. // validating the vc
  1721. //
  1722. DEREF_VC_LOCKED(pVc);
  1723. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: exit\n"));
  1724. return (Status);
  1725. }
  1726. NDIS_STATUS
  1727. PxTapiSetStatusMessages(
  1728. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1729. )
  1730. /*++
  1731. Routine Description:
  1732. TAPI OID action routine
  1733. Arguments:
  1734. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1735. Return Value:
  1736. --*/
  1737. {
  1738. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSeStatusMessages: enter\n"));
  1739. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetStatusMessages: exit\n"));
  1740. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1741. }
  1742. NDIS_STATUS
  1743. PxTapiOpen(
  1744. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1745. )
  1746. /*++
  1747. Routine Description:
  1748. TAPI OID action routine
  1749. Arguments:
  1750. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1751. Return Value:
  1752. --*/
  1753. {
  1754. PNDIS_TAPI_OPEN TapiBuffer =
  1755. (PNDIS_TAPI_OPEN)pNdisTapiRequest->Data;
  1756. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1757. PPX_TAPI_LINE TapiLine;
  1758. PPX_TAPI_ADDR TapiAddr;
  1759. PNDISTAPI_OPENDATA OpenData;
  1760. PX_ADAPTER *Adapter;
  1761. ULONG n;
  1762. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: enter\nn"));
  1763. if (!IsTapiDeviceValid(TapiBuffer->ulDeviceID, &TapiLine)) {
  1764. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOPEN: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->ulDeviceID));
  1765. return(NDISTAPIERR_BADDEVICEID);
  1766. }
  1767. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiOpen: got device %p from ID %d\n", TapiLine, TapiBuffer->ulDeviceID));
  1768. NdisAcquireSpinLock(&TapiLine->Lock);
  1769. if (!(TapiLine->DevStatus->ulDevStatusFlags &
  1770. LINEDEVSTATUSFLAGS_INSERVICE)) {
  1771. NdisReleaseSpinLock(&TapiLine->Lock);
  1772. return(NDISTAPIERR_DEVICEOFFLINE);
  1773. }
  1774. //
  1775. // Stick TAPI's line handle into the device
  1776. //
  1777. TapiLine->htLine = (HTAPI_LINE)TapiBuffer->htLine;
  1778. TapiLine->DevStatus->ulNumOpens++;
  1779. //
  1780. // Stick our line handle into the out param. This is the context that will be
  1781. // passed to us in subsequent API calls on this open line device. Use the device ID.
  1782. //
  1783. TapiBuffer->hdLine = TapiLine->hdLine;
  1784. //
  1785. // Stick the miniport GUID and the mediatype into the variable data portion of the
  1786. // TAPI Open call (req'd for NDISWAN/Tonybe)
  1787. //
  1788. Adapter = TapiLine->TapiProvider->Adapter;
  1789. OpenData = (PNDISTAPI_OPENDATA)
  1790. ((PUCHAR)pNdisTapiRequest->Data + sizeof(NDIS_TAPI_OPEN));
  1791. RtlMoveMemory(&OpenData->Guid,
  1792. &Adapter->Guid,
  1793. sizeof(OpenData->Guid));
  1794. OpenData->MediaType = Adapter->MediumSubType;
  1795. DEREF_TAPILINE_LOCKED(TapiLine);
  1796. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: exit\n"));
  1797. return (NDIS_STATUS_SUCCESS);
  1798. }
  1799. NDIS_STATUS
  1800. PxTapiProviderInit(
  1801. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. TAPI OID action routine
  1806. Arguments:
  1807. fea142c4
  1808. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1809. Return Value:
  1810. --*/
  1811. {
  1812. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: enter\n"));
  1813. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: exit\n"));
  1814. return (NDIS_STATUS_SUCCESS);
  1815. }
  1816. NDIS_STATUS
  1817. PxTapiProviderShutdown(
  1818. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1819. )
  1820. /*++
  1821. Routine Description:
  1822. TAPI OID action routine
  1823. Arguments:
  1824. fea142c4
  1825. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1826. Return Value:
  1827. --*/
  1828. {
  1829. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: enter\n"));
  1830. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: exit\n"));
  1831. return (NDIS_STATUS_SUCCESS);
  1832. }
  1833. NDIS_STATUS
  1834. PxTapiSecureCall(
  1835. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1836. )
  1837. /*++
  1838. Routine Description:
  1839. TAPI OID action routine
  1840. Arguments:
  1841. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1842. Return Value:
  1843. --*/
  1844. {
  1845. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: enter\n"));
  1846. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: exit\n"));
  1847. return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
  1848. }
  1849. NDIS_STATUS
  1850. PxTapiSelectExtVersion(
  1851. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1852. )
  1853. /*++
  1854. Routine Description:
  1855. TAPI OID action routine
  1856. Arguments:
  1857. pNdisTapiRequest -- the request that arrived in an IRP system buffer
  1858. Return Value:
  1859. --*/
  1860. {
  1861. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: enter\n"));
  1862. PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: exit\n"));
  1863. return (NDIS_STATUS_SUCCESS);
  1864. }
  1865. NDIS_STATUS
  1866. PxTapiGatherDigits(
  1867. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1868. )
  1869. {
  1870. NDIS_STATUS Status = STATUS_SUCCESS;
  1871. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits = NULL;
  1872. NDIS_HANDLE NdisBindingHandle, NdisAfHandle, NdisVcHandle;
  1873. PPX_VC pVc = NULL;
  1874. PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiGatherDigits: Enter\n"));
  1875. pNdisTapiGatherDigits =
  1876. (PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
  1877. do {
  1878. PX_REQUEST ProxyRequest;
  1879. PNDIS_REQUEST NdisRequest;
  1880. PIRP Irp;
  1881. if (!IsVcValid(pNdisTapiGatherDigits->hdCall, &pVc)) {
  1882. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  1883. ("PxTapiGatherDigits: Invalid call - Setting "
  1884. "Status NDISTAPIERR_BADDEVICEID\n"));
  1885. Status = NDISTAPIERR_BADDEVICEID;
  1886. break;
  1887. }
  1888. NdisAcquireSpinLock(&pVc->Lock);
  1889. //
  1890. // If we're monitoring digits (ala lineMonitorDigits) then we can't gather digits.
  1891. //
  1892. if (pVc->ulMonitorDigitsModes != 0) {
  1893. NdisReleaseSpinLock(&pVc->Lock);
  1894. Status = NDIS_STATUS_FAILURE;
  1895. break;
  1896. }
  1897. if (pVc->PendingGatherDigits != NULL) {
  1898. //
  1899. // Check if the buffer passed to TSPI_lineGatherDigits was NULL. If so, then this
  1900. // is a request to cancel digit gathering that was previously initiated. If not, then
  1901. // the app is trying to do two lineGatherDigits() operations at once and we have to
  1902. // fail this.
  1903. //
  1904. if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
  1905. pVc->PendingGatherDigits = NULL;
  1906. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
  1907. NdisReleaseSpinLock(&pVc->Lock);
  1908. Status = NDIS_STATUS_SUCCESS;
  1909. break;
  1910. } else {
  1911. NdisReleaseSpinLock(&pVc->Lock);
  1912. Status = NDIS_STATUS_FAILURE;
  1913. break;
  1914. }
  1915. } else if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
  1916. //
  1917. // Trying to cancel digit detection even though it wasn't started. Fail this.
  1918. //
  1919. NdisReleaseSpinLock(&pVc->Lock);
  1920. Status = NDIS_STATUS_FAILURE;
  1921. break;
  1922. }
  1923. Irp = pNdisTapiRequest->Irp;
  1924. IoSetCancelRoutine(Irp, PxCancelSetQuery);
  1925. //
  1926. // Store the unique request ID in the VC - this will be used later to retrieve the
  1927. // original IRP.
  1928. //
  1929. pVc->PendingGatherDigits = pNdisTapiRequest;
  1930. NdisReleaseSpinLock(&pVc->Lock);
  1931. //
  1932. // Initialize the timer that will be used to implement the digit timeouts.
  1933. //
  1934. NdisInitializeTimer(&pVc->DigitTimer,
  1935. PxDigitTimerRoutine,
  1936. (PVOID)pVc);
  1937. //
  1938. // Fill out our request structure.
  1939. //
  1940. NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
  1941. PxInitBlockStruc(&ProxyRequest.Block);
  1942. NdisRequest = &ProxyRequest.NdisRequest;
  1943. NdisRequest->RequestType =
  1944. NdisRequestSetInformation;
  1945. NdisRequest->DATA.SET_INFORMATION.Oid =
  1946. OID_CO_TAPI_REPORT_DIGITS;
  1947. NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
  1948. (PVOID)&pNdisTapiGatherDigits->ulDigitModes; // This is the NDIS_TAPI_GATHER_DIGITS structure
  1949. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
  1950. sizeof(pNdisTapiGatherDigits->ulDigitModes);
  1951. Status =
  1952. NdisCoRequest(pVc->Adapter->ClBindingHandle,
  1953. pVc->ClAf->NdisAfHandle,
  1954. pVc->ClVcHandle,
  1955. NULL,
  1956. NdisRequest);
  1957. if (Status == NDIS_STATUS_PENDING) {
  1958. Status = PxBlock(&ProxyRequest.Block);
  1959. }
  1960. if (Status != NDIS_STATUS_SUCCESS) {
  1961. NdisAcquireSpinLock(&pVc->Lock);
  1962. pVc->PendingGatherDigits = NULL;
  1963. IoSetCancelRoutine(Irp, NULL);
  1964. NdisReleaseSpinLock(&pVc->Lock);
  1965. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  1966. ("PxTapiGatherDigits: NdisCoRequest failed\n"));
  1967. break;
  1968. }
  1969. //
  1970. // Start the timer for the first digit timeout. Ref the VC here because otherwise it might
  1971. // go away before the timer fires.
  1972. //
  1973. if (pNdisTapiGatherDigits->ulFirstDigitTimeout) {
  1974. NdisAcquireSpinLock(&pVc->Lock);
  1975. REF_VC(pVc);
  1976. NdisReleaseSpinLock(&pVc->Lock);
  1977. NdisSetTimer(&pVc->DigitTimer,
  1978. pNdisTapiGatherDigits->ulFirstDigitTimeout);
  1979. }
  1980. //
  1981. // Set status to pending because this request just initiates the gathering of digits.
  1982. // The IRP will complete once all the digits come in.
  1983. //
  1984. Status = NDIS_STATUS_PENDING;
  1985. } while (FALSE);
  1986. DEREF_VC(pVc);
  1987. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  1988. ("PxTapiGatherDigits: Exit - Returning 0x%x\n", Status));
  1989. return (Status);
  1990. }
  1991. NDIS_STATUS
  1992. PxTapiMonitorDigits(
  1993. IN PNDISTAPI_REQUEST pNdisTapiRequest
  1994. )
  1995. {
  1996. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1997. PNDIS_TAPI_MONITOR_DIGITS pNdisTapiMonitorDigits = NULL;
  1998. PPX_VC pVc = NULL;
  1999. PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Enter\n"));
  2000. pNdisTapiMonitorDigits =
  2001. (PNDIS_TAPI_MONITOR_DIGITS)pNdisTapiRequest->Data;
  2002. do {
  2003. if (!IsVcValid(pNdisTapiMonitorDigits->hdCall, &pVc)) {
  2004. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2005. ("PxTapiMonitorDigits: Invalid call - Setting "
  2006. "Status NDISTAPIERR_BADDEVICEID\n"));
  2007. Status = NDISTAPIERR_BADDEVICEID;
  2008. break;
  2009. }
  2010. NdisAcquireSpinLock(&pVc->Lock);
  2011. if (pVc->PendingGatherDigits != NULL) {
  2012. //
  2013. // Can't monitor digits while a lineGatherDigits request is in effect.
  2014. //
  2015. NdisReleaseSpinLock(&pVc->Lock);
  2016. Status = NDIS_STATUS_FAILURE;
  2017. break;
  2018. }
  2019. if (pVc->ulMonitorDigitsModes != 0) {
  2020. NdisReleaseSpinLock(&pVc->Lock);
  2021. //
  2022. // We are already monitoring digits as a result of lineMonitorDigits request.
  2023. // If the digit modes in the this request are zero, then this is a request to
  2024. // cancel digit monitoring.
  2025. //
  2026. if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
  2027. Status = PxStopDigitReporting(pVc);
  2028. if (Status != NDIS_STATUS_SUCCESS) {
  2029. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2030. ("PxTapiMonitorDigits: Failed to stop digit reporting with status 0x%x\n", Status));
  2031. break;
  2032. }
  2033. //
  2034. // It's a shame that I have to acquire and release again since I had
  2035. // the lock before, but there's no way to know whether I can set this
  2036. // to zero until I know the status that PxStopDigitReporting() returned.
  2037. //
  2038. NdisAcquireSpinLock(&pVc->Lock);
  2039. pVc->ulMonitorDigitsModes = 0;
  2040. NdisReleaseSpinLock(&pVc->Lock);
  2041. } else {
  2042. //
  2043. // We're already monitoring digits, so this request to do so must fail.
  2044. //
  2045. Status = NDIS_STATUS_FAILURE;
  2046. break;
  2047. }
  2048. } else {
  2049. PX_REQUEST ProxyRequest;
  2050. PNDIS_REQUEST NdisRequest;
  2051. pVc->ulMonitorDigitsModes = pNdisTapiMonitorDigits->ulDigitModes;
  2052. NdisReleaseSpinLock(&pVc->Lock);
  2053. if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
  2054. //
  2055. // Someone's trying to cancel digit monitoring, but it hasn't been started yet.
  2056. //
  2057. Status = NDIS_STATUS_FAILURE;
  2058. break;
  2059. }
  2060. //
  2061. // Fill out our request structure to tell the miniport to start reporting digits.
  2062. //
  2063. NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
  2064. PxInitBlockStruc(&ProxyRequest.Block);
  2065. NdisRequest = &ProxyRequest.NdisRequest;
  2066. NdisRequest->RequestType =
  2067. NdisRequestSetInformation;
  2068. NdisRequest->DATA.SET_INFORMATION.Oid =
  2069. OID_CO_TAPI_REPORT_DIGITS;
  2070. NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
  2071. (PVOID)&pNdisTapiMonitorDigits->ulDigitModes;
  2072. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
  2073. sizeof(pNdisTapiMonitorDigits->ulDigitModes);
  2074. Status =
  2075. NdisCoRequest(pVc->Adapter->ClBindingHandle,
  2076. pVc->ClAf->NdisAfHandle,
  2077. pVc->ClVcHandle,
  2078. NULL,
  2079. NdisRequest);
  2080. if (Status == NDIS_STATUS_PENDING) {
  2081. Status = PxBlock(&ProxyRequest.Block);
  2082. }
  2083. if (Status != NDIS_STATUS_SUCCESS) {
  2084. NdisAcquireSpinLock(&pVc->Lock);
  2085. pVc->ulMonitorDigitsModes = 0;
  2086. NdisReleaseSpinLock(&pVc->Lock);
  2087. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2088. ("PxTapiMonitorDigits: NdisCoRequest to start digit reporting failed with status 0x%x\n", Status));
  2089. break;
  2090. }
  2091. }
  2092. } while (FALSE);
  2093. DEREF_VC(pVc);
  2094. PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Exit - Returning 0x%x\n", Status));
  2095. return (Status);
  2096. }
  2097. VOID
  2098. PxTapiCompleteDropIrps(
  2099. IN PPX_VC pVc,
  2100. IN ULONG Status
  2101. )
  2102. /*++
  2103. Routine Description:
  2104. Arguments:
  2105. Return Value:
  2106. --*/
  2107. {
  2108. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: Vc %p\n", pVc));
  2109. ASSERT(!IsListEmpty(&pVc->PendingDropReqs));
  2110. ASSERT(pVc->Flags & PX_VC_DROP_PENDING);
  2111. pVc->Flags &= ~PX_VC_DROP_PENDING;
  2112. while (!IsListEmpty(&pVc->PendingDropReqs)) {
  2113. PLIST_ENTRY Entry;
  2114. PIRP Irp;
  2115. KIRQL Irql;
  2116. PNDISTAPI_REQUEST pNdisTapiRequest;
  2117. Entry =
  2118. RemoveHeadList(&pVc->PendingDropReqs);
  2119. NdisReleaseSpinLock(&pVc->Lock);
  2120. pNdisTapiRequest =
  2121. CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
  2122. Irp = pNdisTapiRequest->Irp;
  2123. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  2124. IoSetCancelRoutine(Irp, NULL);
  2125. Irp->IoStatus.Information =
  2126. sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
  2127. Irp->IoStatus.Status = STATUS_SUCCESS;
  2128. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  2129. ("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
  2130. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2131. NdisAcquireSpinLock(&pVc->Lock);
  2132. }
  2133. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: exit\n"));
  2134. return;
  2135. }
  2136. VOID
  2137. PxTapiCompleteAllIrps(
  2138. IN PPX_VC pVc,
  2139. IN ULONG Status
  2140. )
  2141. /*++
  2142. Routine Description:
  2143. Arguments:
  2144. Return Value:
  2145. --*/
  2146. {
  2147. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: Vc %p\n", pVc));
  2148. if (pVc->Flags & PX_VC_DROP_PENDING){
  2149. PxTapiCompleteDropIrps(pVc, Status);
  2150. }
  2151. if (pVc->PendingGatherDigits != NULL) {
  2152. PIRP Irp;
  2153. KIRQL Irql;
  2154. PNDISTAPI_REQUEST pNdisTapiRequest;
  2155. pNdisTapiRequest = pVc->PendingGatherDigits;
  2156. pVc->PendingGatherDigits = NULL;
  2157. NdisReleaseSpinLock(&pVc->Lock);
  2158. Irp = pNdisTapiRequest->Irp;
  2159. ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
  2160. IoSetCancelRoutine(Irp, NULL);
  2161. Irp->IoStatus.Information =
  2162. sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
  2163. Irp->IoStatus.Status = STATUS_SUCCESS;
  2164. PXDEBUGP (PXD_LOUD, PXM_TAPI,
  2165. ("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
  2166. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2167. NdisAcquireSpinLock(&pVc->Lock);
  2168. }
  2169. PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: exit\n"));
  2170. return;
  2171. }
  2172. VOID
  2173. PxIndicateStatus(
  2174. IN PVOID StatusBuffer,
  2175. IN UINT StatusBufferSize
  2176. )
  2177. /*++
  2178. Routine Description:
  2179. Called to send any event info that may be in the device extension to TAPI in the form of an
  2180. NDIS_TAPI_EVENT, sent in an available queued GET_EVENT IRP. If there's no outstanding IRP, stick
  2181. the data in the queue so it will go whenver there is one.
  2182. Arguments:
  2183. Return Value:
  2184. --*/
  2185. {
  2186. PIRP Irp;
  2187. PNDIS_TAPI_EVENT NdisTapiEvent;
  2188. PNDISTAPI_EVENT_DATA NdisTapiEventData;
  2189. NdisTapiEvent = StatusBuffer;
  2190. //
  2191. // Sync event buf access by acquiring EventSpinLock
  2192. //
  2193. NdisAcquireSpinLock(&TspCB.Lock);
  2194. //
  2195. // Are we initialized with TAPI?
  2196. //
  2197. if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
  2198. PXDEBUGP(PXD_WARNING, PXM_TAPI,
  2199. ("PxIndicateStatus: TAPI not connected!\n"));
  2200. NdisReleaseSpinLock(&TspCB.Lock);
  2201. return;
  2202. }
  2203. NdisReleaseSpinLock(&TspCB.Lock);
  2204. NdisAcquireSpinLock(&TspEventList.Lock);
  2205. Irp = TspEventList.RequestIrp;
  2206. TspEventList.RequestIrp = NULL;
  2207. if (Irp == NULL) {
  2208. PPROVIDER_EVENT ProviderEvent;
  2209. ProviderEvent =
  2210. ExAllocateFromNPagedLookasideList(&ProviderEventLookaside);
  2211. if (ProviderEvent != NULL) {
  2212. RtlMoveMemory(&ProviderEvent->Event,
  2213. StatusBuffer,
  2214. sizeof(NDIS_TAPI_EVENT));
  2215. InsertTailList(&TspEventList.List,
  2216. &ProviderEvent->Linkage);
  2217. TspEventList.Count++;
  2218. if (TspEventList.Count > TspEventList.MaxCount) {
  2219. TspEventList.MaxCount = TspEventList.Count;
  2220. }
  2221. }
  2222. } else {
  2223. ASSERT(IsListEmpty(&TspEventList.List));
  2224. }
  2225. NdisReleaseSpinLock(&TspEventList.Lock);
  2226. //
  2227. // Check of there is an outstanding request to satisfy
  2228. //
  2229. if (Irp != NULL) {
  2230. KIRQL Irql;
  2231. //
  2232. // Clear out the cancel routine
  2233. //
  2234. IoSetCancelRoutine (Irp, NULL);
  2235. Irp->IoStatus.Status = STATUS_SUCCESS;
  2236. Irp->IoStatus.Information =
  2237. sizeof(NDISTAPI_EVENT_DATA) + StatusBufferSize - 1;
  2238. //
  2239. // Copy as much of the input data possible from the input data
  2240. // queue to the SystemBuffer to satisfy the read.
  2241. //
  2242. NdisTapiEventData = Irp->AssociatedIrp.SystemBuffer;
  2243. ASSERT(NdisTapiEventData->ulTotalSize >= StatusBufferSize);
  2244. RtlMoveMemory(NdisTapiEventData->Data,
  2245. (PCHAR) StatusBuffer,
  2246. StatusBufferSize);
  2247. //
  2248. // Set the flag so that we start the next packet and complete
  2249. // this read request (with STATUS_SUCCESS) prior to return.
  2250. //
  2251. NdisTapiEventData->ulUsedSize = StatusBufferSize;
  2252. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  2253. ("PxIndicateStatus: htLine: %x, htCall: %x, Msg: %x\n",
  2254. NdisTapiEvent->htLine, NdisTapiEvent->htCall, NdisTapiEvent->ulMsg));
  2255. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  2256. (" : p1: %x, p2: %x, p3: %x\n",
  2257. NdisTapiEvent->ulParam1, NdisTapiEvent->ulParam2, NdisTapiEvent->ulParam3));
  2258. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  2259. }
  2260. }
  2261. NDIS_STATUS
  2262. AllocateTapiResources(
  2263. IN PPX_ADAPTER ClAdapter,
  2264. IN PPX_CL_AF pClAf
  2265. )
  2266. {
  2267. NDIS_STATUS Status;
  2268. ULONG SizeNeeded;
  2269. ULONG TapiVersion;
  2270. PPX_TAPI_LINE TapiLine = NULL;
  2271. PPX_TAPI_ADDR TapiAddr = NULL;
  2272. UINT i, j;
  2273. PPX_TAPI_PROVIDER TapiProvider;
  2274. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiResoures: Enter\n"));
  2275. //
  2276. // See if this device supports TAPI and if so
  2277. // see how many lines it has
  2278. //
  2279. TapiProvider =
  2280. AllocateTapiProvider(ClAdapter, pClAf);
  2281. if (TapiProvider == NULL) {
  2282. PXDEBUGP(PXD_ERROR, PXM_TAPI, ("Error allocating TapiProvider!\n"));
  2283. return (NDIS_STATUS_FAILURE);
  2284. }
  2285. return (NDIS_STATUS_SUCCESS);
  2286. }
  2287. PPX_TAPI_PROVIDER
  2288. AllocateTapiProvider(
  2289. PPX_ADAPTER ClAdapter,
  2290. PPX_CL_AF pClAf
  2291. )
  2292. {
  2293. PNDIS_REQUEST NdisRequest;
  2294. NDIS_STATUS Status;
  2295. CO_TAPI_CM_CAPS CmCaps;
  2296. BOOLEAN TapiSupported = TRUE;
  2297. ULONG AllocSize;
  2298. PPX_TAPI_PROVIDER TapiProvider = NULL;
  2299. ULONG i;
  2300. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiProvider: Enter\n"));
  2301. do {
  2302. PX_REQUEST ProxyRequest;
  2303. PPX_REQUEST pProxyRequest = &ProxyRequest;
  2304. NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
  2305. NdisZeroMemory(&CmCaps, sizeof(CmCaps));
  2306. PxInitBlockStruc (&pProxyRequest->Block);
  2307. NdisRequest = &pProxyRequest->NdisRequest;
  2308. NdisRequest->RequestType =
  2309. NdisRequestQueryInformation;
  2310. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2311. OID_CO_TAPI_CM_CAPS;
  2312. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2313. &CmCaps;
  2314. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2315. sizeof(CmCaps);
  2316. Status =
  2317. NdisCoRequest(ClAdapter->ClBindingHandle,
  2318. pClAf->NdisAfHandle,
  2319. NULL,
  2320. NULL,
  2321. NdisRequest);
  2322. if (Status == NDIS_STATUS_PENDING) {
  2323. Status = PxBlock(&pProxyRequest->Block);
  2324. }
  2325. if (Status != NDIS_STATUS_SUCCESS) {
  2326. if (Status != NDIS_STATUS_NOT_SUPPORTED) {
  2327. break;
  2328. }
  2329. Status = NDIS_STATUS_SUCCESS;
  2330. //
  2331. // Setup a default config for this device.
  2332. // ToDo! These values should be read from
  2333. // the registry on a per device basis!
  2334. //
  2335. CmCaps.ulNumLines = 1;
  2336. CmCaps.ulFlags = 0;
  2337. CmCaps.ulCoTapiVersion = CO_TAPI_VERSION;
  2338. TapiSupported = FALSE;
  2339. }
  2340. //
  2341. // Allocate a tapi provider block for this adapter
  2342. // The provider block will live outside of the
  2343. // adapter. This allows us to continue tapi service
  2344. // after a machine has been power managed.
  2345. //
  2346. AllocSize = sizeof(PX_TAPI_PROVIDER) +
  2347. (sizeof(PPX_TAPI_LINE) * CmCaps.ulNumLines) +
  2348. sizeof(PVOID);
  2349. PxAllocMem(TapiProvider, AllocSize, PX_PROVIDER_TAG);
  2350. if (TapiProvider == NULL) {
  2351. break;
  2352. }
  2353. NdisZeroMemory(TapiProvider, AllocSize);
  2354. NdisAllocateSpinLock(&TapiProvider->Lock);
  2355. TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
  2356. TapiProvider->Adapter = ClAdapter;
  2357. TapiProvider->ClAf = pClAf;
  2358. TapiProvider->NumDevices = CmCaps.ulNumLines;
  2359. TapiProvider->Guid = ClAdapter->Guid;
  2360. TapiProvider->Af = pClAf->Af;
  2361. 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",
  2362. TapiProvider->Guid.Data1, TapiProvider->Guid.Data2, TapiProvider->Guid.Data3,
  2363. TapiProvider->Guid.Data4[0],TapiProvider->Guid.Data4[1],TapiProvider->Guid.Data4[2],
  2364. TapiProvider->Guid.Data4[3],TapiProvider->Guid.Data4[4],TapiProvider->Guid.Data4[5],
  2365. TapiProvider->Guid.Data4[6],TapiProvider->Guid.Data4[7]));
  2366. TapiProvider->TapiSupported = TapiSupported;
  2367. TapiProvider->TapiFlags |= CmCaps.ulFlags;
  2368. TapiProvider->CoTapiVersion = CmCaps.ulCoTapiVersion;
  2369. InitializeListHead(&TapiProvider->LineList);
  2370. InitializeListHead(&TapiProvider->CreateList);
  2371. for (i = 0; i < TapiProvider->NumDevices; i++) {
  2372. PPX_TAPI_LINE TapiLine;
  2373. TapiLine =
  2374. AllocateTapiLine(TapiProvider, i);
  2375. if (TapiLine == NULL) {
  2376. FreeTapiProvider(TapiProvider);
  2377. TapiProvider = NULL;
  2378. break;
  2379. }
  2380. //
  2381. // Put the new line on the create list
  2382. // We will need to insert it in the line table
  2383. // and possibly notify tapi about it
  2384. //
  2385. InsertTailList(&TapiProvider->CreateList, &TapiLine->Linkage);
  2386. }
  2387. } while ( FALSE );
  2388. if (TapiProvider != NULL) {
  2389. PPX_TAPI_PROVIDER tp;
  2390. BOOLEAN TapiConnected;
  2391. //
  2392. // See if we already have a provider for this
  2393. // GUID. If we don't just add this provider on
  2394. // to the tsp and do the right thing with it's
  2395. // new lines. If we do see if anything on the
  2396. // provider has changed and do the right thing
  2397. // with it's tapi lines.
  2398. //
  2399. NdisAcquireSpinLock(&TspCB.Lock);
  2400. tp = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
  2401. while ((PVOID)tp != (PVOID)&TspCB.ProviderList) {
  2402. if ((tp->Status == PROVIDER_STATUS_OFFLINE) &&
  2403. (NdisEqualMemory(&tp->Guid, &TapiProvider->Guid, sizeof(tp->Guid))) &&
  2404. (pClAf->Af.AddressFamily == tp->Af.AddressFamily)) {
  2405. //
  2406. // We have already have a provider for this
  2407. // adapter/address family. See if anything has
  2408. // changed.
  2409. //
  2410. //
  2411. // ToDo!
  2412. // This check needs to be more complete!
  2413. //
  2414. if (tp->NumDevices != TapiProvider->NumDevices) {
  2415. //
  2416. // ToDo!
  2417. // Much work to do here!
  2418. //
  2419. } else {
  2420. //
  2421. // Nothing has changed so free the new allocations
  2422. // and reactivate the old ones.
  2423. //
  2424. FreeTapiProvider(TapiProvider);
  2425. TapiProvider = tp;
  2426. }
  2427. 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",
  2428. ClAdapter->Guid.Data1, ClAdapter->Guid.Data2, ClAdapter->Guid.Data3,
  2429. ClAdapter->Guid.Data4[0],ClAdapter->Guid.Data4[1],ClAdapter->Guid.Data4[2],
  2430. ClAdapter->Guid.Data4[3],ClAdapter->Guid.Data4[4],ClAdapter->Guid.Data4[5],
  2431. ClAdapter->Guid.Data4[6],ClAdapter->Guid.Data4[7]));
  2432. break;
  2433. } else {
  2434. tp = (PPX_TAPI_PROVIDER)tp->Linkage.Flink;
  2435. }
  2436. }
  2437. //
  2438. // We did not find a provider on the list
  2439. // so insert the new provider
  2440. //
  2441. if ((PVOID)tp == (PVOID)&TspCB.ProviderList) {
  2442. InsertTailList(&TspCB.ProviderList, &TapiProvider->Linkage);
  2443. TspCB.NdisTapiNumDevices += TapiProvider->NumDevices;
  2444. }
  2445. if (TspCB.Status == NDISTAPI_STATUS_CONNECTED) {
  2446. TapiProvider->Status = PROVIDER_STATUS_ONLINE;
  2447. }
  2448. NdisReleaseSpinLock(&TspCB.Lock);
  2449. NdisAcquireSpinLock(&TapiProvider->Lock);
  2450. pClAf->TapiProvider = TapiProvider;
  2451. TapiProvider->ClAf= pClAf;
  2452. TapiProvider->Adapter = ClAdapter;
  2453. while (!IsListEmpty(&TapiProvider->CreateList)) {
  2454. PPX_TAPI_LINE TapiLine;
  2455. TapiLine = (PPX_TAPI_LINE)
  2456. RemoveHeadList(&TapiProvider->CreateList);
  2457. InsertTailList(&TapiProvider->LineList, &TapiLine->Linkage);
  2458. //
  2459. // Insert the line in the table
  2460. //
  2461. if (!InsertLineInTable(TapiLine)) {
  2462. FreeTapiLine(TapiLine);
  2463. continue;
  2464. }
  2465. NdisReleaseSpinLock(&TapiProvider->Lock);
  2466. SendTapiLineCreate(TapiLine);
  2467. NdisAcquireSpinLock(&TapiProvider->Lock);
  2468. }
  2469. MarkProviderOnline(TapiProvider);
  2470. NdisReleaseSpinLock(&TapiProvider->Lock);
  2471. }
  2472. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider: %x\n", TapiProvider));
  2473. return (TapiProvider);
  2474. }
  2475. VOID
  2476. MarkProviderOffline(
  2477. PPX_TAPI_PROVIDER TapiProvider
  2478. )
  2479. {
  2480. LOCK_STATE LockState;
  2481. ULONG i;
  2482. TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
  2483. TapiProvider->ClAf = NULL;
  2484. TapiProvider->Adapter = NULL;
  2485. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2486. for (i = 0; i < LineTable.Size; i++) {
  2487. PPX_TAPI_LINE TapiLine;
  2488. TapiLine = LineTable.Table[i];
  2489. if (TapiLine != NULL) {
  2490. NdisAcquireSpinLock(&TapiLine->Lock);
  2491. if (TapiLine->TapiProvider == TapiProvider) {
  2492. TapiLine->DevStatus->ulDevStatusFlags &=
  2493. ~(LINEDEVSTATUSFLAGS_INSERVICE);
  2494. TapiLine->ClAf = NULL;
  2495. NdisReleaseSpinLock(&TapiLine->Lock);
  2496. #if 0
  2497. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2498. SendTapiLineClose(TapiLine);
  2499. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2500. #endif
  2501. } else {
  2502. NdisReleaseSpinLock(&TapiLine->Lock);
  2503. }
  2504. }
  2505. }
  2506. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2507. }
  2508. VOID
  2509. MarkProviderOnline(
  2510. PPX_TAPI_PROVIDER TapiProvider
  2511. )
  2512. {
  2513. LOCK_STATE LockState;
  2514. ULONG i;
  2515. TapiProvider->Status = PROVIDER_STATUS_ONLINE;
  2516. NdisReleaseSpinLock(&TapiProvider->Lock);
  2517. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2518. for (i = 0; i < LineTable.Size; i++) {
  2519. PPX_TAPI_LINE TapiLine;
  2520. TapiLine = LineTable.Table[i];
  2521. if (TapiLine != NULL) {
  2522. NdisAcquireSpinLock(&TapiLine->Lock);
  2523. if (TapiLine->TapiProvider == TapiProvider) {
  2524. TapiLine->DevStatus->ulDevStatusFlags |=
  2525. LINEDEVSTATUSFLAGS_INSERVICE;
  2526. TapiLine->ClAf = TapiProvider->ClAf;
  2527. //#if 0
  2528. //
  2529. // This line was open by tapi before it was
  2530. // marked offline. We need to force tapi to
  2531. // reopen the line so we will send the CLOSE_LINE
  2532. // message in the hopes that any apps that care
  2533. // will then turn around and reopen the line.
  2534. //
  2535. if (TapiLine->DevStatus->ulNumOpens != 0) {
  2536. // TapiLine->DevStatus->ulNumOpens = 0;
  2537. NdisReleaseSpinLock(&TapiLine->Lock);
  2538. SendTapiLineClose(TapiLine);
  2539. NdisAcquireSpinLock(&TapiLine->Lock);
  2540. }
  2541. //#endif
  2542. }
  2543. NdisReleaseSpinLock(&TapiLine->Lock);
  2544. }
  2545. }
  2546. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2547. NdisAcquireSpinLock(&TapiProvider->Lock);
  2548. }
  2549. VOID
  2550. MarkProviderConnected(
  2551. PPX_TAPI_PROVIDER TapiProvider
  2552. )
  2553. {
  2554. LOCK_STATE LockState;
  2555. ULONG i;
  2556. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2557. for (i = 0; i < LineTable.Size; i++) {
  2558. PPX_TAPI_LINE TapiLine;
  2559. TapiLine = LineTable.Table[i];
  2560. if (TapiLine != NULL) {
  2561. NdisAcquireSpinLock(&TapiLine->Lock);
  2562. if (TapiLine->TapiProvider == TapiProvider) {
  2563. TapiLine->DevStatus->ulDevStatusFlags |=
  2564. LINEDEVSTATUSFLAGS_CONNECTED;
  2565. }
  2566. NdisReleaseSpinLock(&TapiLine->Lock);
  2567. }
  2568. }
  2569. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2570. }
  2571. VOID
  2572. MarkProviderDisconnected(
  2573. PPX_TAPI_PROVIDER TapiProvider
  2574. )
  2575. {
  2576. LOCK_STATE LockState;
  2577. ULONG i;
  2578. //
  2579. // ToDo! If we have any active calls on this line we
  2580. // need to disconnect them without tapi's assistance. This
  2581. // would only happen if tapi crashes while we have active calls
  2582. //
  2583. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2584. for (i = 0; i < LineTable.Size; i++) {
  2585. PPX_TAPI_LINE TapiLine;
  2586. TapiLine = LineTable.Table[i];
  2587. if (TapiLine != NULL) {
  2588. NdisAcquireSpinLock(&TapiLine->Lock);
  2589. if (TapiLine->TapiProvider == TapiProvider) {
  2590. TapiLine->DevStatus->ulDevStatusFlags &=
  2591. ~(LINEDEVSTATUSFLAGS_CONNECTED);
  2592. }
  2593. NdisReleaseSpinLock(&TapiLine->Lock);
  2594. }
  2595. }
  2596. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2597. }
  2598. VOID
  2599. ClearSapWithTapiLine(
  2600. PPX_CL_SAP pClSap
  2601. )
  2602. {
  2603. LOCK_STATE LockState;
  2604. ULONG i;
  2605. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  2606. for (i = 0; i < LineTable.Size; i++) {
  2607. PPX_TAPI_LINE TapiLine;
  2608. TapiLine = LineTable.Table[i];
  2609. if (TapiLine != NULL) {
  2610. NdisAcquireSpinLock(&TapiLine->Lock);
  2611. if (TapiLine->ClSap == pClSap) {
  2612. TapiLine->ClSap = NULL;
  2613. }
  2614. NdisReleaseSpinLock(&TapiLine->Lock);
  2615. }
  2616. }
  2617. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  2618. }
  2619. VOID
  2620. FreeTapiProvider(
  2621. PPX_TAPI_PROVIDER TapiProvider
  2622. )
  2623. {
  2624. //
  2625. // Free any lines on the create list
  2626. //
  2627. while (!IsListEmpty(&TapiProvider->CreateList)) {
  2628. PPX_TAPI_LINE TapiLine;
  2629. TapiLine = (PPX_TAPI_LINE)
  2630. RemoveHeadList(&TapiProvider->CreateList);
  2631. FreeTapiLine(TapiLine);
  2632. }
  2633. //
  2634. // Free the lines associated with this provider
  2635. //
  2636. while (!IsListEmpty(&TapiProvider->LineList)) {
  2637. PPX_TAPI_LINE TapiLine;
  2638. TapiLine = (PPX_TAPI_LINE)
  2639. RemoveHeadList(&TapiProvider->LineList);
  2640. if (TapiLine->Flags & PX_LINE_IN_TABLE) {
  2641. RemoveTapiLineFromTable(TapiLine);
  2642. }
  2643. FreeTapiLine(TapiLine);
  2644. }
  2645. NdisFreeSpinLock(&TapiProvider->Lock);
  2646. PxFreeMem(TapiProvider);
  2647. }
  2648. PPX_TAPI_LINE
  2649. AllocateTapiLine(
  2650. PPX_TAPI_PROVIDER TapiProvider,
  2651. ULONG LineNumber
  2652. )
  2653. {
  2654. PLINE_DEV_CAPS ldc;
  2655. PNDIS_REQUEST NdisRequest;
  2656. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2657. PCO_TAPI_LINE_CAPS LineCaps;
  2658. PUCHAR EnumBuffer;
  2659. #if DBG
  2660. ULONG EnumBufferSize = PAGE_SIZE -
  2661. sizeof(PXD_ALLOCATION);
  2662. #else
  2663. ULONG EnumBufferSize = PAGE_SIZE;
  2664. #endif
  2665. ULONG SizeNeeded, SizeDevCaps;
  2666. PPX_TAPI_LINE TapiLine = NULL;
  2667. PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
  2668. PPX_CL_AF pClAf = TapiProvider->ClAf;
  2669. ULONG i;
  2670. PX_REQUEST ProxyRequest;
  2671. PPX_REQUEST pProxyRequest = &ProxyRequest;
  2672. PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
  2673. if (EnumBuffer == NULL) {
  2674. return (NULL);
  2675. }
  2676. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2677. LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
  2678. LineCaps->ulLineID = LineNumber;
  2679. ldc = &LineCaps->LineDevCaps;
  2680. ldc->ulTotalSize =
  2681. EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
  2682. //
  2683. // If this device does not support TAPI we will build
  2684. // a default line configuration.
  2685. // ToDo! Some of these values should be queried from
  2686. // the registry on a per device basis!
  2687. //
  2688. if (!TapiProvider->TapiSupported) {
  2689. NDIS_CO_LINK_SPEED SpeedInfo;
  2690. LineCaps->ulFlags = 0;
  2691. ldc->ulTotalSize =
  2692. ldc->ulNeededSize =
  2693. ldc->ulUsedSize =
  2694. sizeof(LINE_DEV_CAPS);
  2695. ldc->ulStringFormat = STRINGFORMAT_ASCII;
  2696. ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
  2697. ldc->ulNumAddresses = 1;
  2698. ldc->ulBearerModes = LINEBEARERMODE_VOICE |
  2699. LINEBEARERMODE_DATA;
  2700. ldc->ulMediaModes = LINEMEDIAMODE_DIGITALDATA;
  2701. ldc->ulMaxNumActiveCalls = 1000;
  2702. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  2703. PxInitBlockStruc (&pProxyRequest->Block);
  2704. NdisRequest = &pProxyRequest->NdisRequest;
  2705. NdisRequest->RequestType =
  2706. NdisRequestQueryInformation;
  2707. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2708. OID_GEN_CO_LINK_SPEED;
  2709. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2710. &SpeedInfo;
  2711. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2712. sizeof(NDIS_CO_LINK_SPEED);
  2713. PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: DeviceExtension->RegistryFlags = %x\n", DeviceExtension->RegistryFlags));
  2714. PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: using ndisrequest to get rates from adapter\n"));
  2715. Status =
  2716. NdisCoRequest(ClAdapter->ClBindingHandle,
  2717. pClAf->NdisAfHandle,
  2718. NULL,
  2719. NULL,
  2720. NdisRequest);
  2721. if (Status == NDIS_STATUS_PENDING) {
  2722. Status = PxBlock(&pProxyRequest->Block);
  2723. }
  2724. if (Status == NDIS_STATUS_SUCCESS) {
  2725. ldc->ulMaxRate = SpeedInfo.Outbound;
  2726. } else {
  2727. ldc->ulMaxRate = 128000;
  2728. }
  2729. } else if (!(TapiProvider->TapiFlags & CO_TAPI_FLAG_PER_LINE_CAPS) &&
  2730. (LineNumber > 0)) {
  2731. PLINE_DEV_CAPS ldc1;
  2732. PCO_TAPI_LINE_CAPS LineCaps1;
  2733. PPX_TAPI_LINE Line1;
  2734. //
  2735. // If all of the lines on this device have the same caps
  2736. // and this is not the first line, just copy the caps
  2737. // from the first line!
  2738. //
  2739. Line1 = (PPX_TAPI_LINE)
  2740. TapiProvider->CreateList.Flink;
  2741. ldc1 = Line1->DevCaps;
  2742. if (ldc1->ulTotalSize > ldc->ulTotalSize) {
  2743. //
  2744. // We don't have enough memory allocated!
  2745. //
  2746. PxFreeMem(EnumBuffer);
  2747. EnumBufferSize =
  2748. (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS) +
  2749. ldc1->ulTotalSize);
  2750. PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
  2751. if (EnumBuffer == NULL){
  2752. return (NULL);
  2753. }
  2754. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2755. LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
  2756. LineCaps->ulLineID = LineNumber;
  2757. LineCaps->LineDevCaps.ulTotalSize =
  2758. EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) -
  2759. sizeof(LINE_DEV_CAPS));
  2760. ldc = &LineCaps->LineDevCaps;
  2761. }
  2762. NdisMoveMemory(ldc, ldc1, ldc1->ulUsedSize);
  2763. } else {
  2764. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  2765. PxInitBlockStruc (&pProxyRequest->Block);
  2766. NdisRequest = &pProxyRequest->NdisRequest;
  2767. NdisRequest->RequestType =
  2768. NdisRequestQueryInformation;
  2769. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2770. OID_CO_TAPI_LINE_CAPS;
  2771. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2772. LineCaps;
  2773. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2774. EnumBufferSize;
  2775. Status =
  2776. NdisCoRequest(ClAdapter->ClBindingHandle,
  2777. pClAf->NdisAfHandle,
  2778. NULL,
  2779. NULL,
  2780. NdisRequest);
  2781. if (Status == NDIS_STATUS_PENDING) {
  2782. Status = PxBlock(&pProxyRequest->Block);
  2783. }
  2784. if (Status == NDIS_STATUS_INVALID_LENGTH){
  2785. //
  2786. // Our buffer was not large enough so try again
  2787. //
  2788. EnumBufferSize =
  2789. MAX (LineCaps->LineDevCaps.ulNeededSize,
  2790. NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
  2791. PxFreeMem(EnumBuffer);
  2792. PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
  2793. if (EnumBuffer == NULL){
  2794. return(NULL);
  2795. }
  2796. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2797. LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
  2798. LineCaps->ulLineID = LineNumber;
  2799. ldc = &LineCaps->LineDevCaps;
  2800. ldc->ulTotalSize =
  2801. EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
  2802. NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
  2803. PxInitBlockStruc (&pProxyRequest->Block);
  2804. NdisRequest = &pProxyRequest->NdisRequest;
  2805. NdisRequest->RequestType =
  2806. NdisRequestQueryInformation;
  2807. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  2808. OID_CO_TAPI_LINE_CAPS;
  2809. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  2810. LineCaps;
  2811. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  2812. EnumBufferSize;
  2813. Status =
  2814. NdisCoRequest(ClAdapter->ClBindingHandle,
  2815. pClAf->NdisAfHandle,
  2816. NULL,
  2817. NULL,
  2818. NdisRequest);
  2819. if (Status == NDIS_STATUS_PENDING){
  2820. Status = PxBlock(&pProxyRequest->Block);
  2821. }
  2822. if (Status != NDIS_STATUS_SUCCESS){
  2823. PxFreeMem(EnumBuffer);
  2824. return(NULL);
  2825. }
  2826. }else if (Status != STATUS_SUCCESS){
  2827. PxFreeMem(EnumBuffer);
  2828. return(NULL);
  2829. }
  2830. }
  2831. SizeNeeded = sizeof(PX_TAPI_LINE);
  2832. SizeNeeded +=
  2833. (sizeof(PPX_TAPI_ADDR) * LineCaps->LineDevCaps.ulNumAddresses);
  2834. SizeNeeded += sizeof(LINE_DEV_STATUS);
  2835. SizeNeeded += 3*sizeof(PVOID);
  2836. if (LineCaps->LineDevCaps.ulUsedSize < sizeof(LINE_DEV_CAPS)) {
  2837. LineCaps->LineDevCaps.ulUsedSize = sizeof(LINE_DEV_CAPS);
  2838. }
  2839. SizeDevCaps = LineCaps->LineDevCaps.ulUsedSize;
  2840. SizeNeeded += SizeDevCaps;
  2841. PxAllocMem(TapiLine, SizeNeeded, PX_TAPILINE_TAG);
  2842. if (TapiLine == NULL){
  2843. PxFreeMem(EnumBuffer);
  2844. return(NULL);
  2845. }
  2846. NdisZeroMemory(TapiLine, SizeNeeded);
  2847. TapiLine->DevCaps = (PLINE_DEV_CAPS)
  2848. ((PUCHAR)TapiLine + sizeof(PX_TAPI_LINE) + sizeof(PVOID));
  2849. (ULONG_PTR)TapiLine->DevCaps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  2850. TapiLine->DevStatus = (PLINE_DEV_STATUS)
  2851. ((PUCHAR)TapiLine->DevCaps + SizeDevCaps + sizeof(PVOID));
  2852. (ULONG_PTR)TapiLine->DevStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  2853. TapiLine->AddrTable.Table = (PPX_TAPI_ADDR*)
  2854. ((PUCHAR)TapiLine->DevStatus +
  2855. sizeof(LINE_DEV_STATUS) + sizeof(PVOID));
  2856. (ULONG_PTR)TapiLine->AddrTable.Table &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  2857. NdisMoveMemory(TapiLine->DevCaps,
  2858. &LineCaps->LineDevCaps,
  2859. LineCaps->LineDevCaps.ulUsedSize);
  2860. ldc = TapiLine->DevCaps;
  2861. //
  2862. // Proxy fills some fields on behalf of all cm/miniports
  2863. //
  2864. ldc->ulPermanentLineID =
  2865. TapiProvider->Guid.Data1 + LineNumber;
  2866. ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
  2867. ldc->ulAnswerMode = LINEANSWERMODE_NONE;
  2868. ldc->ulLineStates = LINEDEVSTATE_CONNECTED |
  2869. LINEDEVSTATE_DISCONNECTED |
  2870. LINEDEVSTATE_OPEN |
  2871. LINEDEVSTATE_CLOSE |
  2872. LINEDEVSTATE_INSERVICE |
  2873. LINEDEVSTATE_OUTOFSERVICE |
  2874. LINEDEVSTATE_REMOVED;
  2875. ldc->ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
  2876. ldc->PermanentLineGuid = TapiProvider->Guid;
  2877. ldc->ulTotalSize =
  2878. ldc->ulNeededSize =
  2879. ldc->ulUsedSize;
  2880. TapiLine->TapiProvider = TapiProvider;
  2881. TapiLine->CmLineID = LineNumber;
  2882. TapiLine->Flags |= LineCaps->ulFlags;
  2883. TapiLine->DevStatus->ulTotalSize =
  2884. TapiLine->DevStatus->ulNeededSize =
  2885. TapiLine->DevStatus->ulUsedSize = sizeof(LINE_DEV_STATUS);
  2886. TapiLine->ClAf = pClAf;
  2887. TapiLine->RefCount= 1;
  2888. //
  2889. // Build the address table for this line
  2890. //
  2891. InitializeListHead(&TapiLine->AddrTable.List);
  2892. NdisAllocateSpinLock(&TapiLine->Lock);
  2893. TapiLine->AddrTable.Size = TapiLine->DevCaps->ulNumAddresses;
  2894. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  2895. ("Allocated TapiLine %p LineId %d \n", TapiLine, TapiLine->CmLineID));
  2896. for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++) {
  2897. PPX_TAPI_ADDR TapiAddr;
  2898. TapiAddr =
  2899. AllocateTapiAddr(TapiProvider, TapiLine, i);
  2900. if (TapiAddr == NULL) {
  2901. FreeTapiLine(TapiLine);
  2902. TapiLine = NULL;
  2903. break;
  2904. }
  2905. //
  2906. // Insert the address in the line's address table
  2907. //
  2908. TapiLine->AddrTable.Table[i] = TapiAddr;
  2909. InsertTailList(&TapiLine->AddrTable.List,
  2910. &TapiAddr->Linkage);
  2911. TapiLine->AddrTable.Count++;
  2912. }
  2913. PxFreeMem(EnumBuffer);
  2914. return (TapiLine);
  2915. }
  2916. VOID
  2917. FreeTapiLine(
  2918. PPX_TAPI_LINE TapiLine
  2919. )
  2920. {
  2921. ULONG i;
  2922. for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++){
  2923. PPX_TAPI_ADDR TapiAddr;
  2924. //
  2925. // Remove the address from the line table
  2926. //
  2927. TapiAddr = TapiLine->AddrTable.Table[i];
  2928. if (TapiAddr != NULL) {
  2929. RemoveEntryList(&TapiAddr->Linkage);
  2930. TapiLine->AddrTable.Table[i] = NULL;
  2931. TapiLine->AddrTable.Count--;
  2932. //
  2933. // Free the address memory
  2934. //
  2935. FreeTapiAddr(TapiAddr);
  2936. }
  2937. }
  2938. NdisFreeSpinLock(&TapiLine->Lock);
  2939. //
  2940. // Free the line memory
  2941. //
  2942. PxFreeMem(TapiLine);
  2943. }
  2944. PPX_TAPI_ADDR
  2945. AllocateTapiAddr(
  2946. PPX_TAPI_PROVIDER TapiProvider,
  2947. PPX_TAPI_LINE TapiLine,
  2948. ULONG AddrID
  2949. )
  2950. {
  2951. PPX_TAPI_ADDR TapiAddr;
  2952. PUCHAR EnumBuffer;
  2953. #if DBG
  2954. ULONG EnumBufferSize = PAGE_SIZE -
  2955. sizeof(PXD_ALLOCATION);
  2956. #else
  2957. ULONG EnumBufferSize = PAGE_SIZE;
  2958. #endif
  2959. PNDIS_REQUEST NdisRequest;
  2960. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2961. ULONG SizeNeeded;
  2962. PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
  2963. PPX_CL_AF pClAf = TapiProvider->ClAf;
  2964. PX_REQUEST ProxyRequest;
  2965. PPX_REQUEST pProxyRequest = &ProxyRequest;
  2966. PLINE_ADDRESS_CAPS ac;
  2967. PCO_TAPI_ADDRESS_CAPS AddrCaps;
  2968. PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
  2969. if (EnumBuffer == NULL){
  2970. return(NULL);
  2971. }
  2972. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  2973. AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
  2974. AddrCaps->ulLineID = TapiLine->CmLineID;
  2975. AddrCaps->ulAddressID = AddrID;
  2976. ac = &AddrCaps->LineAddressCaps;
  2977. ac->ulTotalSize =
  2978. EnumBufferSize - (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
  2979. //
  2980. // If this device does not support TAPI we will
  2981. // build a default address.
  2982. // ToDo! Some of these values should be queried from
  2983. // the registry on a per device basis!
  2984. //
  2985. if (!TapiProvider->TapiSupported){
  2986. ac->ulTotalSize =
  2987. ac->ulNeededSize =
  2988. ac->ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
  2989. ac->ulMaxNumActiveCalls = 1000;
  2990. }else if (!(TapiLine->Flags & CO_TAPI_FLAG_PER_ADDRESS_CAPS) &&
  2991. (AddrID > 0)){
  2992. PLINE_ADDRESS_CAPS ac1;
  2993. PCO_TAPI_ADDRESS_CAPS AddrCaps1;
  2994. PPX_TAPI_ADDR Addr1;
  2995. //
  2996. // If all of the addresses on this line have the same
  2997. // caps and this is not the first address, just copy
  2998. // the caps from the first address!
  2999. //
  3000. Addr1 = (PPX_TAPI_ADDR)
  3001. TapiLine->AddrTable.List.Flink;
  3002. ac1 = Addr1->Caps;
  3003. if (ac1->ulTotalSize > ac->ulTotalSize){
  3004. //
  3005. // We don't have enough memory allocated!
  3006. //
  3007. PxFreeMem(EnumBuffer);
  3008. EnumBufferSize =
  3009. (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS) +
  3010. ac1->ulTotalSize);
  3011. PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
  3012. if (EnumBuffer == NULL){
  3013. return (NULL);
  3014. }
  3015. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  3016. AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
  3017. AddrCaps->ulLineID = TapiLine->CmLineID;
  3018. AddrCaps->ulAddressID = AddrID;
  3019. AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
  3020. (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
  3021. }
  3022. ac = &AddrCaps->LineAddressCaps;
  3023. NdisMoveMemory(ac, ac1, ac1->ulUsedSize);
  3024. }else{
  3025. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  3026. PxInitBlockStruc (&pProxyRequest->Block);
  3027. NdisRequest = &pProxyRequest->NdisRequest;
  3028. NdisRequest->RequestType =
  3029. NdisRequestQueryInformation;
  3030. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  3031. OID_CO_TAPI_ADDRESS_CAPS;
  3032. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  3033. AddrCaps;
  3034. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  3035. EnumBufferSize;
  3036. Status =
  3037. NdisCoRequest(ClAdapter->ClBindingHandle,
  3038. pClAf->NdisAfHandle,
  3039. NULL,
  3040. NULL,
  3041. NdisRequest);
  3042. if (Status == NDIS_STATUS_PENDING){
  3043. Status = PxBlock(&pProxyRequest->Block);
  3044. }
  3045. if (Status == NDIS_STATUS_INVALID_LENGTH){
  3046. //
  3047. // Our buffer was not large enough so try again
  3048. //
  3049. SizeNeeded =
  3050. EnumBufferSize =
  3051. NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
  3052. PxFreeMem(EnumBuffer);
  3053. PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
  3054. if (EnumBuffer == NULL){
  3055. return(NULL);
  3056. }
  3057. NdisZeroMemory(EnumBuffer, EnumBufferSize);
  3058. AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
  3059. AddrCaps->ulLineID = TapiLine->CmLineID;
  3060. AddrCaps->ulAddressID = AddrID;
  3061. AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
  3062. (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
  3063. NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
  3064. PxInitBlockStruc (&pProxyRequest->Block);
  3065. NdisRequest = &pProxyRequest->NdisRequest;
  3066. NdisRequest->RequestType =
  3067. NdisRequestQueryInformation;
  3068. NdisRequest->DATA.QUERY_INFORMATION.Oid =
  3069. OID_CO_TAPI_ADDRESS_CAPS;
  3070. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  3071. AddrCaps;
  3072. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  3073. EnumBufferSize;
  3074. Status =
  3075. NdisCoRequest(ClAdapter->ClBindingHandle,
  3076. pClAf->NdisAfHandle,
  3077. NULL,
  3078. NULL,
  3079. NdisRequest);
  3080. if (Status == NDIS_STATUS_PENDING){
  3081. Status = PxBlock(&pProxyRequest->Block);
  3082. }
  3083. if (Status != NDIS_STATUS_SUCCESS){
  3084. PxFreeMem(EnumBuffer);
  3085. return(NULL);
  3086. }
  3087. }else if (Status != STATUS_SUCCESS){
  3088. PxFreeMem(EnumBuffer);
  3089. return(NULL);
  3090. }
  3091. }
  3092. if (AddrCaps->LineAddressCaps.ulUsedSize < sizeof(LINE_ADDRESS_CAPS)) {
  3093. AddrCaps->LineAddressCaps.ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
  3094. }
  3095. SizeNeeded = sizeof(PX_TAPI_ADDR);
  3096. SizeNeeded += AddrCaps->LineAddressCaps.ulUsedSize;
  3097. SizeNeeded += sizeof(LINE_ADDRESS_STATUS);
  3098. SizeNeeded += 2*sizeof(PVOID);
  3099. PxAllocMem(TapiAddr, SizeNeeded, PX_TAPIADDR_TAG);
  3100. if (TapiAddr == NULL){
  3101. PxFreeMem(EnumBuffer);
  3102. return (NULL);
  3103. }
  3104. NdisZeroMemory((PUCHAR)TapiAddr, SizeNeeded);
  3105. TapiAddr->Caps = (PLINE_ADDRESS_CAPS)
  3106. ((PUCHAR)TapiAddr + sizeof(PX_TAPI_ADDR) + sizeof(PVOID));
  3107. (ULONG_PTR)TapiAddr->Caps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  3108. TapiAddr->AddrStatus = (PLINE_ADDRESS_STATUS)
  3109. ((PUCHAR)TapiAddr->Caps +
  3110. AddrCaps->LineAddressCaps.ulUsedSize + sizeof(PVOID));
  3111. (ULONG_PTR)TapiAddr->AddrStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  3112. NdisMoveMemory(TapiAddr->Caps,
  3113. &AddrCaps->LineAddressCaps,
  3114. AddrCaps->LineAddressCaps.ulUsedSize);
  3115. //
  3116. // Proxy fills some fields on behalf of all cm/miniports
  3117. //
  3118. ac = TapiAddr->Caps;
  3119. if (ac->ulTotalSize < ac->ulUsedSize) {
  3120. ac->ulTotalSize = ac->ulUsedSize;
  3121. }
  3122. if (ac->ulNeededSize < ac->ulNeededSize) {
  3123. ac->ulNeededSize = ac->ulUsedSize;
  3124. }
  3125. ac->ulLineDeviceID = TapiLine->ulDeviceID;
  3126. ac->ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
  3127. ac->ulAddressStates = LINEADDRESSSTATE_NUMCALLS;
  3128. ac->ulCallInfoStates = LINECALLINFOSTATE_BEARERMODE |
  3129. LINECALLINFOSTATE_RATE |
  3130. LINECALLINFOSTATE_MEDIAMODE;
  3131. ac->ulCallStates = LINECALLSTATE_IDLE |
  3132. LINECALLSTATE_OFFERING |
  3133. LINECALLSTATE_ACCEPTED |
  3134. LINECALLSTATE_BUSY |
  3135. LINECALLSTATE_CONNECTED |
  3136. LINECALLSTATE_PROCEEDING |
  3137. LINECALLSTATE_DISCONNECTED;
  3138. ac->ulDialToneModes = 0;
  3139. ac->ulBusyModes = LINEBUSYMODE_UNAVAIL;
  3140. ac->ulSpecialInfo = 0;
  3141. ac->ulDisconnectModes = LINEDISCONNECTMODE_NORMAL |
  3142. LINEDISCONNECTMODE_BUSY |
  3143. LINEDISCONNECTMODE_NOANSWER;
  3144. TapiAddr->TapiLine = TapiLine;
  3145. TapiAddr->AddrId = AddrID;
  3146. PxFreeMem(EnumBuffer);
  3147. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Allocated TapiAddr %p AddrId %d for TapiLine %p\n", TapiAddr, TapiAddr->AddrId, TapiLine));
  3148. return (TapiAddr);
  3149. }
  3150. VOID
  3151. FreeTapiAddr(
  3152. PPX_TAPI_ADDR TapiAddr
  3153. )
  3154. {
  3155. //
  3156. // ToDo! we need to tear down all
  3157. // active calls on this address.
  3158. //
  3159. PxFreeMem(TapiAddr);
  3160. }
  3161. NDIS_STATUS
  3162. AllocateTapiCallInfo(
  3163. PPX_VC pVc,
  3164. LINE_CALL_INFO UNALIGNED *LineCallInfo
  3165. )
  3166. {
  3167. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3168. ULONG SizeNeeded;
  3169. if (pVc->CallInfo) {
  3170. PxFreeMem(pVc->CallInfo);
  3171. }
  3172. if (LineCallInfo != NULL) {
  3173. SizeNeeded = LineCallInfo->ulUsedSize;
  3174. } else {
  3175. SizeNeeded = sizeof(LINE_CALL_INFO) + LINE_CALL_INFO_VAR_DATA_SIZE;
  3176. }
  3177. PxAllocMem(pVc->CallInfo, SizeNeeded, PX_LINECALLINFO_TAG);
  3178. if (pVc->CallInfo == NULL) {
  3179. return (NDIS_STATUS_RESOURCES);
  3180. }
  3181. pVc->ulCallInfoFieldsChanged = 0;
  3182. NdisZeroMemory(pVc->CallInfo, SizeNeeded);
  3183. if (LineCallInfo != NULL) {
  3184. NdisMoveMemory(pVc->CallInfo,
  3185. LineCallInfo,
  3186. LineCallInfo->ulUsedSize);
  3187. } else {
  3188. pVc->CallInfo->ulTotalSize = SizeNeeded;
  3189. pVc->CallInfo->ulNeededSize = SizeNeeded;
  3190. pVc->CallInfo->ulUsedSize = sizeof(LINE_CALL_INFO);
  3191. }
  3192. return (Status);
  3193. }
  3194. BOOLEAN
  3195. InsertVcInTable(
  3196. PPX_VC pVc
  3197. )
  3198. {
  3199. ULONG i;
  3200. ULONG index;
  3201. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3202. LOCK_STATE LockState;
  3203. PPX_CL_AF pClAf;
  3204. NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
  3205. if (VcTable.Count == VcTable.Size) {
  3206. ULONG SizeNeeded;
  3207. PUCHAR AllocatedMemory;
  3208. PPX_VC *NewTable;
  3209. //
  3210. // Grow the table
  3211. //
  3212. SizeNeeded =
  3213. (VcTable.Size + VcTable.Size/2) * sizeof(PPX_VC);
  3214. PxAllocMem(AllocatedMemory, SizeNeeded, PX_VCTABLE_TAG);
  3215. if (AllocatedMemory == NULL) {
  3216. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3217. return (FALSE);
  3218. }
  3219. RtlZeroMemory(AllocatedMemory,SizeNeeded);
  3220. NewTable = (PPX_VC*)AllocatedMemory;
  3221. RtlMoveMemory((PUCHAR)NewTable,
  3222. (PUCHAR)VcTable.Table,
  3223. (sizeof(PPX_VC) * VcTable.Size));
  3224. PxFreeMem(VcTable.Table);
  3225. VcTable.Table = NewTable;
  3226. VcTable.Size += VcTable.Size/2;
  3227. }
  3228. i = VcTable.Size;
  3229. index = VcTable.NextSlot;
  3230. do {
  3231. if (VcTable.Table[index] == NULL) {
  3232. NdisDprAcquireSpinLock(&pVc->Lock);
  3233. pVc->hdCall = index;
  3234. VcTable.Table[index] = pVc;
  3235. InsertTailList(&VcTable.List,
  3236. &pVc->Linkage);
  3237. VcTable.Count++;
  3238. VcTable.NextSlot =
  3239. (VcTable.NextSlot + 1) % VcTable.Size;
  3240. pVc->Flags |= PX_VC_IN_TABLE;
  3241. pClAf = pVc->ClAf;
  3242. NdisDprReleaseSpinLock(&pVc->Lock);
  3243. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Inserting pVc %x in VcTable hdCall %d\n", pVc, pVc->hdCall));
  3244. break;
  3245. }
  3246. index = (index+1) % VcTable.Size;
  3247. } while (--i);
  3248. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3249. if (i != 0) {
  3250. NdisAcquireSpinLock(&pClAf->Lock);
  3251. REF_CL_AF(pClAf);
  3252. InsertTailList(&pClAf->VcList, &pVc->ClAfLinkage);
  3253. NdisReleaseSpinLock(&pClAf->Lock);
  3254. } else {
  3255. PXDEBUGP(PXD_TAPI,PXM_TAPI, ("Failed to insert pVc %x in VcTable\n", pVc));
  3256. }
  3257. return (i != 0);
  3258. }
  3259. VOID
  3260. RemoveVcFromTable(
  3261. PPX_VC pVc
  3262. )
  3263. {
  3264. LOCK_STATE LockState;
  3265. PPX_CL_AF pClAf;
  3266. PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Removing pVc %x from VcTable hdCall %d\n", pVc, pVc->hdCall));
  3267. NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
  3268. ASSERT(VcTable.Table[pVc->hdCall] == pVc);
  3269. VcTable.Table[pVc->hdCall] = NULL;
  3270. VcTable.Count--;
  3271. NdisDprAcquireSpinLock(&pVc->Lock);
  3272. RemoveEntryList(&pVc->Linkage);
  3273. pVc->Flags &= ~PX_VC_IN_TABLE;
  3274. pClAf = pVc->ClAf;
  3275. NdisDprReleaseSpinLock(&pVc->Lock);
  3276. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3277. NdisAcquireSpinLock(&pClAf->Lock);
  3278. RemoveEntryList(&pVc->ClAfLinkage);
  3279. DEREF_CL_AF_LOCKED(pClAf);
  3280. }
  3281. BOOLEAN
  3282. IsTapiLineValid(
  3283. ULONG hdLine,
  3284. PPX_TAPI_LINE *TapiLine
  3285. )
  3286. {
  3287. LOCK_STATE LockState;
  3288. ULONG i;
  3289. *TapiLine = NULL;
  3290. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  3291. for (i = 0; i < LineTable.Size; i++) {
  3292. PPX_TAPI_LINE RetLine;
  3293. RetLine = LineTable.Table[i];
  3294. if ((RetLine != NULL) &&
  3295. (RetLine->hdLine == hdLine)) {
  3296. *TapiLine = RetLine;
  3297. NdisDprAcquireSpinLock(&RetLine->Lock);
  3298. REF_TAPILINE(RetLine);
  3299. NdisDprReleaseSpinLock(&RetLine->Lock);
  3300. break;
  3301. }
  3302. }
  3303. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3304. return (*TapiLine != NULL);
  3305. }
  3306. BOOLEAN
  3307. IsTapiDeviceValid(
  3308. ULONG ulDeviceID,
  3309. PPX_TAPI_LINE *TapiLine
  3310. )
  3311. {
  3312. LOCK_STATE LockState;
  3313. ULONG i;
  3314. *TapiLine = NULL;
  3315. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  3316. for (i = 0; i < LineTable.Size; i++) {
  3317. PPX_TAPI_LINE RetLine;
  3318. RetLine = LineTable.Table[i];
  3319. if ((RetLine != NULL) &&
  3320. (RetLine->ulDeviceID == ulDeviceID)) {
  3321. *TapiLine = RetLine;
  3322. NdisDprAcquireSpinLock(&RetLine->Lock);
  3323. REF_TAPILINE(RetLine);
  3324. NdisDprReleaseSpinLock(&RetLine->Lock);
  3325. break;
  3326. }
  3327. }
  3328. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3329. return (*TapiLine != NULL);
  3330. }
  3331. BOOLEAN
  3332. IsVcValid(
  3333. ULONG_PTR CallId,
  3334. PPX_VC *pVc
  3335. )
  3336. {
  3337. PPX_VC RetVc = NULL;
  3338. LOCK_STATE LockState;
  3339. ULONG i;
  3340. NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
  3341. if (CallId < VcTable.Size) {
  3342. RetVc = VcTable.Table[CallId];
  3343. }
  3344. if (RetVc != NULL) {
  3345. NdisDprAcquireSpinLock(&RetVc->Lock);
  3346. REF_VC(RetVc);
  3347. NdisDprReleaseSpinLock(&RetVc->Lock);
  3348. }
  3349. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3350. *pVc = RetVc;
  3351. return (RetVc != NULL);
  3352. }
  3353. VOID
  3354. GetVcFromCtx(
  3355. NDIS_HANDLE VcCtx,
  3356. PPX_VC *pVc
  3357. )
  3358. {
  3359. PPX_VC RetVc = NULL;
  3360. ULONG_PTR i;
  3361. LOCK_STATE LockState;
  3362. NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
  3363. i = (ULONG_PTR)(VcCtx);
  3364. if (i < VcTable.Size) {
  3365. RetVc = VcTable.Table[i];
  3366. }
  3367. if (RetVc != NULL) {
  3368. NdisDprAcquireSpinLock(&RetVc->Lock);
  3369. REF_VC(RetVc);
  3370. NdisDprReleaseSpinLock(&RetVc->Lock);
  3371. }
  3372. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  3373. *pVc = RetVc;
  3374. }
  3375. //
  3376. // Function assumes that the TapiLine's spinlock is held!
  3377. //
  3378. BOOLEAN
  3379. IsAddressValid(
  3380. PPX_TAPI_LINE TapiLine,
  3381. ULONG AddressId,
  3382. PPX_TAPI_ADDR *TapiAddr
  3383. )
  3384. {
  3385. PPX_TAPI_ADDR RetAddr = NULL;
  3386. do {
  3387. if (AddressId >= TapiLine->AddrTable.Count) {
  3388. break;
  3389. }
  3390. RetAddr = TapiLine->AddrTable.Table[AddressId];
  3391. } while (FALSE);
  3392. *TapiAddr = RetAddr;
  3393. return (RetAddr != NULL);
  3394. }
  3395. BOOLEAN
  3396. GetLineFromCmLineID(
  3397. PPX_TAPI_PROVIDER TapiProvider,
  3398. ULONG CmLineID,
  3399. PPX_TAPI_LINE *TapiLine
  3400. )
  3401. {
  3402. PPX_TAPI_LINE RetLine;
  3403. NdisAcquireSpinLock(&TapiProvider->Lock);
  3404. RetLine = (PPX_TAPI_LINE)
  3405. TapiProvider->LineList.Flink;
  3406. while ((PVOID)RetLine != (PVOID)&TapiProvider->LineList) {
  3407. if ((RetLine->CmLineID == CmLineID) &&
  3408. (RetLine->DevStatus->ulNumOpens != 0)) {
  3409. break;
  3410. }
  3411. RetLine = (PPX_TAPI_LINE)
  3412. RetLine->Linkage.Flink;
  3413. }
  3414. if ((PVOID)RetLine == (PVOID)&TapiProvider->LineList) {
  3415. RetLine = NULL;
  3416. }
  3417. NdisReleaseSpinLock(&TapiProvider->Lock);
  3418. *TapiLine = RetLine;
  3419. return (RetLine != NULL);
  3420. }
  3421. BOOLEAN
  3422. GetAvailLineFromProvider(
  3423. PPX_TAPI_PROVIDER TapiProvider,
  3424. PPX_TAPI_LINE *TapiLine,
  3425. PPX_TAPI_ADDR *TapiAddr
  3426. )
  3427. {
  3428. LOCK_STATE LockState;
  3429. ULONG i;
  3430. PPX_TAPI_LINE tl;
  3431. NdisAcquireSpinLock(&TapiProvider->Lock);
  3432. tl = (PPX_TAPI_LINE)TapiProvider->LineList.Flink;
  3433. while ((PVOID)tl != (PVOID)&TapiProvider->LineList) {
  3434. PTAPI_ADDR_TABLE AddrTable;
  3435. PPX_TAPI_ADDR ta;
  3436. NdisDprAcquireSpinLock(&tl->Lock);
  3437. if (tl->DevStatus->ulNumOpens != 0) {
  3438. AddrTable = &tl->AddrTable;
  3439. ta = (PPX_TAPI_ADDR)AddrTable->List.Flink;
  3440. //
  3441. // Walk the addresses on this line
  3442. //
  3443. while ((PVOID)ta != (PVOID)&AddrTable->List) {
  3444. //
  3445. // If this address has a callcount that is
  3446. // < then the max num it supports, add another
  3447. // call on this address!
  3448. //
  3449. if (ta->CallCount < ta->Caps->ulMaxNumActiveCalls) {
  3450. *TapiLine = tl;
  3451. *TapiAddr = ta;
  3452. NdisDprReleaseSpinLock(&tl->Lock);
  3453. NdisReleaseSpinLock(&TapiProvider->Lock);
  3454. return (TRUE);
  3455. }
  3456. ta = (PPX_TAPI_ADDR)ta->Linkage.Flink;
  3457. }
  3458. }
  3459. NdisDprReleaseSpinLock(&tl->Lock);
  3460. tl = (PPX_TAPI_LINE)tl->Linkage.Flink;
  3461. }
  3462. NdisReleaseSpinLock(&TapiProvider->Lock);
  3463. return (FALSE);
  3464. }
  3465. //
  3466. // Function assumes that the TapiLine's spinlock is held!
  3467. //
  3468. PPX_TAPI_ADDR
  3469. GetAvailAddrFromLine(
  3470. PPX_TAPI_LINE TapiLine
  3471. )
  3472. {
  3473. PPX_TAPI_ADDR TapiAddr;
  3474. PTAPI_ADDR_TABLE AddrTable;
  3475. AddrTable = &TapiLine->AddrTable;
  3476. TapiAddr = (PPX_TAPI_ADDR)AddrTable->List.Flink;
  3477. //
  3478. // Walk the addresses on this line
  3479. //
  3480. while ((PVOID)TapiAddr != (PVOID)&AddrTable->List) {
  3481. //
  3482. // If this address has a callcount that is
  3483. // < then the max num it supports, add another
  3484. // call on this address!
  3485. //
  3486. if (TapiAddr->CallCount <
  3487. TapiAddr->Caps->ulMaxNumActiveCalls) {
  3488. return (TapiAddr);
  3489. }
  3490. TapiAddr = (PPX_TAPI_ADDR)TapiAddr->Linkage.Flink;
  3491. }
  3492. return (NULL);
  3493. }
  3494. BOOLEAN
  3495. InsertLineInTable(
  3496. PPX_TAPI_LINE TapiLine
  3497. )
  3498. {
  3499. ULONG i;
  3500. ULONG index;
  3501. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3502. LOCK_STATE LockState;
  3503. NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
  3504. if (LineTable.Count == LineTable.Size) {
  3505. ULONG SizeNeeded;
  3506. PUCHAR AllocatedMemory;
  3507. PPX_TAPI_LINE *NewTable;
  3508. //
  3509. // Grow the table
  3510. //
  3511. SizeNeeded =
  3512. (LineTable.Size + LineTable.Size/2) * sizeof(PPX_TAPI_LINE);
  3513. PxAllocMem(AllocatedMemory, SizeNeeded, PX_LINETABLE_TAG);
  3514. if (AllocatedMemory == NULL) {
  3515. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3516. return (FALSE);
  3517. }
  3518. RtlZeroMemory(AllocatedMemory,SizeNeeded);
  3519. NewTable = (PPX_TAPI_LINE*)AllocatedMemory;
  3520. RtlMoveMemory((PUCHAR)NewTable,
  3521. (PUCHAR)LineTable.Table,
  3522. (sizeof(PPX_TAPI_LINE) * LineTable.Size));
  3523. PxFreeMem(LineTable.Table);
  3524. LineTable.Table = NewTable;
  3525. LineTable.Size += LineTable.Size/2;
  3526. }
  3527. i = LineTable.Size;
  3528. index = LineTable.NextSlot;
  3529. do {
  3530. if (LineTable.Table[index] == NULL) {
  3531. TapiLine->hdLine = index;
  3532. TapiLine->Flags |= PX_LINE_IN_TABLE;
  3533. LineTable.Table[index] = TapiLine;
  3534. LineTable.Count++;
  3535. LineTable.NextSlot =
  3536. (LineTable.NextSlot + 1) % LineTable.Size;
  3537. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  3538. ("Inserting TapiLine %p in LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
  3539. break;
  3540. }
  3541. index = (index+1) % LineTable.Size;
  3542. } while (--i);
  3543. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3544. #if DBG
  3545. if (i == 0) {
  3546. PXDEBUGP(PXD_TAPI,PXM_TAPI,
  3547. ("Failed to insert TapiLine %p in LineTable\n", TapiLine));
  3548. }
  3549. #endif
  3550. return (i != 0);
  3551. }
  3552. VOID
  3553. RemoveTapiLineFromTable(
  3554. PPX_TAPI_LINE TapiLine
  3555. )
  3556. {
  3557. LOCK_STATE LockState;
  3558. PXDEBUGP(PXD_TAPI, PXM_TAPI,
  3559. ("Removing TapiLine %p from LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
  3560. NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
  3561. ASSERT(LineTable.Table[TapiLine->hdLine] == TapiLine);
  3562. LineTable.Table[TapiLine->hdLine] = NULL;
  3563. TapiLine->Flags &= ~PX_LINE_IN_TABLE;
  3564. LineTable.Count--;
  3565. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  3566. }
  3567. NDIS_STATUS
  3568. PxVcCleanup(
  3569. PPX_VC pVc,
  3570. ULONG Flags
  3571. )
  3572. {
  3573. NDIS_STATUS Status;
  3574. PXDEBUGP(PXD_LOUD, PXM_TAPI,
  3575. ("PxVcCleanup: Vc %p, State: %x, HandoffState: %x VcFlags: %x, NewFlags: %x\n",
  3576. pVc, pVc->State, pVc->HandoffState, Flags, pVc->Flags, Flags));
  3577. //
  3578. // Terminate Digit Gathering or Monitoring.
  3579. //
  3580. if (pVc->ulMonitorDigitsModes != 0) {
  3581. NdisReleaseSpinLock(&pVc->Lock);
  3582. PxStopDigitReporting(pVc);
  3583. NdisAcquireSpinLock(&pVc->Lock);
  3584. pVc->ulMonitorDigitsModes = 0;
  3585. } else if (pVc->PendingGatherDigits != NULL) {
  3586. PNDISTAPI_REQUEST pNdisTapiRequest = pVc->PendingGatherDigits;
  3587. pVc->PendingGatherDigits = NULL;
  3588. PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
  3589. }
  3590. switch (pVc->State) {
  3591. case PX_VC_IDLE:
  3592. //
  3593. // Already idle do nothing.
  3594. //
  3595. Status = NDIS_STATUS_SUCCESS;
  3596. break;
  3597. case PX_VC_PROCEEDING:
  3598. //
  3599. // We have an outgoing call, when it completes close
  3600. // it down with ndis and complete the drop when
  3601. // in PxClCloseCallComplete.
  3602. //
  3603. pVc->PrevState = pVc->State;
  3604. pVc->State = PX_VC_DISCONNECTING;
  3605. //
  3606. // Attempt to close the call directly
  3607. // if this fails we will cleanup when
  3608. // the outgoing call completes
  3609. //
  3610. pVc->Flags |= (PX_VC_OUTCALL_ABORTING |
  3611. PX_VC_CLEANUP_CM |
  3612. Flags);
  3613. PxCloseCallWithCm(pVc);
  3614. Status = NDIS_STATUS_PENDING;
  3615. break;
  3616. case PX_VC_OFFERING:
  3617. //
  3618. // We have an incoming call offered to tapi. Close
  3619. // it down now by calling it's callcomplete handler
  3620. // with a non-success value.
  3621. //
  3622. pVc->Flags |= (Flags |
  3623. PX_VC_INCALL_ABORTING);
  3624. pVc->PrevState = pVc->State;
  3625. if (pVc->Flags & PX_VC_CLEANUP_CM) {
  3626. pVc->State= PX_VC_DISCONNECTING;
  3627. } else {
  3628. pVc->State = PX_VC_IDLE;
  3629. }
  3630. if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
  3631. PxStopIncomingCallTimeout(pVc);
  3632. }
  3633. NdisReleaseSpinLock(&pVc->Lock);
  3634. NdisClIncomingCallComplete(NDIS_STATUS_FAILURE,
  3635. pVc->ClVcHandle,
  3636. pVc->pCallParameters);
  3637. NdisAcquireSpinLock(&pVc->Lock);
  3638. if (pVc->Flags & PX_VC_CLEANUP_CM) {
  3639. PxCloseCallWithCm(pVc);
  3640. } else {
  3641. SendTapiCallState(pVc,
  3642. LINECALLSTATE_DISCONNECTED,
  3643. 0,
  3644. pVc->CallInfo->ulMediaMode);
  3645. //
  3646. // Remove the ref applied in PxClIncomingCall.
  3647. // Don't use the full deref code here as the
  3648. // ref applied when we mapped the vc will
  3649. // keep the vc around.
  3650. //
  3651. pVc->RefCount--;
  3652. }
  3653. Status = NDIS_STATUS_SUCCESS;
  3654. break;
  3655. case PX_VC_DISCONNECTING:
  3656. pVc->Flags |= (Flags);
  3657. Status = NDIS_STATUS_PENDING;
  3658. break;
  3659. case PX_VC_CONNECTED:
  3660. //
  3661. // We have a call that needs to be closed with ndis.
  3662. // This may include dropping the call with a client
  3663. // depending on the handoff state. Complete the drop
  3664. // irp in PxClCloseCallComplete
  3665. //
  3666. if (!(pVc->Flags & PX_VC_DROP_PENDING)) {
  3667. pVc->PrevState = pVc->State;
  3668. pVc->State = PX_VC_DISCONNECTING;
  3669. pVc->Flags |= (Flags | PX_VC_CLEANUP_CM);
  3670. Status =
  3671. PxCloseCallWithCl(pVc);
  3672. if (Status != NDIS_STATUS_PENDING) {
  3673. PxCloseCallWithCm(pVc);
  3674. }
  3675. }
  3676. Status = NDIS_STATUS_PENDING;
  3677. break;
  3678. default:
  3679. PXDEBUGP(PXD_FATAL, PXM_TAPI,
  3680. ("PxVcCleanup: Invalid VcState! Vc: %p VcState: %x CallState: %x\n",
  3681. pVc, pVc->State, pVc->ulCallState ));
  3682. Status = NDIS_STATUS_FAILURE;
  3683. ASSERT(0);
  3684. break;
  3685. }
  3686. return (Status);
  3687. }