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.

4928 lines
142 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Module Name:
  3. tapi.c
  4. Abstract:
  5. This module contains all the TAPI_OID processing routines.
  6. Author:
  7. Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
  8. Environment:
  9. Windows 2000 kernel mode Miniport driver or equivalent.
  10. Revision History:
  11. ---------------------------------------------------------------------------*/
  12. #include <ntddk.h>
  13. #include <ntddndis.h>
  14. #include <ndis.h>
  15. #include <ndiswan.h>
  16. #include <ndistapi.h>
  17. #include <ntverp.h>
  18. #include "debug.h"
  19. #include "timer.h"
  20. #include "bpool.h"
  21. #include "ppool.h"
  22. #include "util.h"
  23. #include "packet.h"
  24. #include "protocol.h"
  25. #include "miniport.h"
  26. #include "tapi.h"
  27. #include "fsm.h"
  28. extern TIMERQ gl_TimerQ;
  29. extern NPAGED_LOOKASIDE_LIST gl_llistWorkItems;
  30. ///////////////////////////////////////////////////////////////////////////////////
  31. //
  32. // Tapi provider, line and call context functions
  33. //
  34. ///////////////////////////////////////////////////////////////////////////////////
  35. VOID
  36. ReferenceCall(
  37. IN CALL* pCall,
  38. IN BOOLEAN fAcquireLock
  39. )
  40. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  41. Functional Description:
  42. This function will increment the reference count on the call object.
  43. CAUTION: If fAcquireLock is set, this function will acquire the lock for the
  44. call, otherwise it will assume the caller owns the lock.
  45. Parameters:
  46. pCall _ A pointer to our call information structure.
  47. fAcquireLock _ Indicates if the caller already has the lock or not.
  48. Caller must set this flag to FALSE if it has the lock,
  49. otherwise it must be supplied as TRUE.
  50. Return Values:
  51. None
  52. ---------------------------------------------------------------------------*/
  53. {
  54. LONG lRef;
  55. TRACE( TL_V, TM_Tp, ("+ReferenceCall") );
  56. if ( fAcquireLock )
  57. NdisAcquireSpinLock( &pCall->lockCall );
  58. lRef = ++pCall->lRef;
  59. if ( fAcquireLock )
  60. NdisReleaseSpinLock( &pCall->lockCall );
  61. TRACE( TL_V, TM_Tp, ("-ReferenceCall=$%d",lRef) );
  62. }
  63. VOID
  64. DereferenceCall(
  65. IN CALL *pCall
  66. )
  67. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  68. Functional Description:
  69. This function will decrement the reference count on the call object
  70. If ref count drops to 0 (which means the call has been closed),
  71. it will set the CLBF_CallClosed bit. Then it will call TpCloseCallComplete()
  72. function which eventually handles destroying the resources allocated for
  73. this call context.
  74. CAUTION: All locks must be released before calling this function because
  75. it may cause a set of cascading events.
  76. Parameters:
  77. pCall _ A pointer ot our call information structure.
  78. Return Values:
  79. None
  80. ---------------------------------------------------------------------------*/
  81. {
  82. BOOLEAN fCallTpCloseCallComplete = FALSE;
  83. LONG lRef;
  84. TRACE( TL_V, TM_Tp, ("+DereferenceCall") );
  85. NdisAcquireSpinLock( &pCall->lockCall );
  86. lRef = --pCall->lRef;
  87. if ( lRef == 0 )
  88. {
  89. pCall->ulClFlags &= ~CLBF_CallOpen;
  90. pCall->ulClFlags &= ~CLBF_CallClosePending;
  91. pCall->ulClFlags |= CLBF_CallClosed;
  92. fCallTpCloseCallComplete = TRUE;
  93. }
  94. NdisReleaseSpinLock( &pCall->lockCall );
  95. if ( fCallTpCloseCallComplete )
  96. TpCloseCallComplete( pCall );
  97. TRACE( TL_V, TM_Tp, ("-DereferenceCall=$%d",lRef) );
  98. }
  99. VOID
  100. ReferenceLine(
  101. IN LINE* pLine,
  102. IN BOOLEAN fAcquireLock
  103. )
  104. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  105. Functional Description:
  106. This function will increment the reference count on the line object.
  107. CAUTION: If fAcquireLock is set, this function will acquire the lock for the
  108. line, otherwise it will assume the caller owns the lock.
  109. Parameters:
  110. pLine _ A pointer to our line information structure.
  111. fAcquireLock _ Indicates if the caller already has the lock or not.
  112. Caller must set this flag to FALSE if it has the lock,
  113. otherwise it must be supplied as TRUE.
  114. Return Values:
  115. None
  116. ---------------------------------------------------------------------------*/
  117. {
  118. LONG lRef;
  119. TRACE( TL_V, TM_Tp, ("+ReferenceLine") );
  120. if ( fAcquireLock )
  121. NdisAcquireSpinLock( &pLine->lockLine );
  122. lRef = ++pLine->lRef;
  123. if ( fAcquireLock )
  124. NdisReleaseSpinLock( &pLine->lockLine );
  125. TRACE( TL_V, TM_Tp, ("-ReferenceLine=$%d",lRef) );
  126. }
  127. VOID
  128. DereferenceLine(
  129. IN LINE *pLine
  130. )
  131. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  132. Functional Description:
  133. This function will decrement the reference count on the line object
  134. If the ref count drops to 0 (which means the line has been closed),
  135. it will set the LNBF_CallClosed bit. Then it will call TpCloseLineComplete()
  136. function which eventually handles destroying the resources allocated for
  137. this line context.
  138. CAUTION: All locks must be released before calling this function because
  139. it may cause a set of cascading events.
  140. Parameters:
  141. pLine _ A pointer to our line information structure.
  142. Return Values:
  143. None
  144. ---------------------------------------------------------------------------*/
  145. {
  146. BOOLEAN fCallTpCloseLineComplete = FALSE;
  147. LONG lRef;
  148. TRACE( TL_V, TM_Tp, ("+DereferenceLine") );
  149. NdisAcquireSpinLock( &pLine->lockLine );
  150. lRef = --pLine->lRef;
  151. if ( lRef == 0 )
  152. {
  153. pLine->ulLnFlags &= ~LNBF_LineOpen;
  154. pLine->ulLnFlags &= ~LNBF_LineClosePending;
  155. pLine->ulLnFlags |= LNBF_LineClosed;
  156. fCallTpCloseLineComplete = TRUE;
  157. }
  158. NdisReleaseSpinLock( &pLine->lockLine );
  159. if ( fCallTpCloseLineComplete )
  160. TpCloseLineComplete( pLine );
  161. TRACE( TL_V, TM_Tp, ("-DereferenceLine=$%d",lRef) );
  162. }
  163. VOID
  164. ReferenceTapiProv(
  165. IN ADAPTER* pAdapter,
  166. IN BOOLEAN fAcquireLock
  167. )
  168. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  169. Functional Description:
  170. This function will increment the reference count on the tapi prov object.
  171. CAUTION: If fAcquireLock is set, this function will acquire the lock for the
  172. line, otherwise it will assume the caller owns the lock.
  173. Parameters:
  174. pAdapter _ A pointer to our adapter information structure.
  175. fAcquireLock _ Indicates if the caller already has the lock or not.
  176. Caller must set this flag to FALSE if it has the lock,
  177. otherwise it must be supplied as TRUE.
  178. Return Values:
  179. None
  180. ---------------------------------------------------------------------------*/
  181. {
  182. LONG lRef;
  183. TRACE( TL_V, TM_Tp, ("+ReferenceTapiProv") );
  184. if ( fAcquireLock )
  185. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  186. lRef = ++pAdapter->TapiProv.lRef;
  187. if ( fAcquireLock )
  188. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  189. TRACE( TL_V, TM_Tp, ("-ReferenceTapiProv=$%d",lRef) );
  190. }
  191. VOID
  192. DereferenceTapiProv(
  193. IN ADAPTER *pAdapter
  194. )
  195. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  196. Functional Description:
  197. This function will decrement the reference count on the tapi prov object
  198. CAUTION: All locks must be released before calling this function because
  199. it may cause a set of cascading events.
  200. Parameters:
  201. pAdapter _ A pointer to our adapter line information structure.
  202. Return Values:
  203. None
  204. ---------------------------------------------------------------------------*/
  205. {
  206. BOOLEAN fCallTpProviderShutdownComplete = FALSE;
  207. LONG lRef;
  208. TRACE( TL_V, TM_Tp, ("+DereferenceTapiProv") );
  209. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  210. lRef = --pAdapter->TapiProv.lRef;
  211. if ( lRef == 0 )
  212. {
  213. pAdapter->TapiProv.ulTpFlags &= ~TPBF_TapiProvInitialized;
  214. pAdapter->TapiProv.ulTpFlags &= ~TPBF_TapiProvShutdownPending;
  215. pAdapter->TapiProv.ulTpFlags |= TPBF_TapiProvShutdown;
  216. fCallTpProviderShutdownComplete = TRUE;
  217. }
  218. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  219. if ( fCallTpProviderShutdownComplete )
  220. TpProviderShutdownComplete( pAdapter );
  221. TRACE( TL_V, TM_Tp, ("-DereferenceTapiProv=$%d",lRef) );
  222. }
  223. NDIS_STATUS
  224. TpProviderInitialize(
  225. IN ADAPTER* pAdapter,
  226. IN PNDIS_TAPI_PROVIDER_INITIALIZE pRequest
  227. )
  228. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  229. Functional Description:
  230. This request initializes the TAPI portion of the miniport.
  231. It will set Tapi Provider's state to initialize, and reference both the
  232. owning adapter and tapi provider.
  233. Parameters:
  234. Adapter _ A pointer ot our adapter information structure.
  235. Request _ A pointer to the NDIS_TAPI request structure for this call.
  236. typedef struct _NDIS_TAPI_PROVIDER_INITIALIZE
  237. {
  238. IN ULONG ulRequestID;
  239. IN ULONG ulDeviceIDBase;
  240. OUT ULONG ulNumLineDevs;
  241. OUT ULONG ulProviderID;
  242. } NDIS_TAPI_PROVIDER_INITIALIZE, *PNDIS_TAPI_PROVIDER_INITIALIZE;
  243. Return Values:
  244. NDIS_STATUS_SUCCESS
  245. ---------------------------------------------------------------------------*/
  246. {
  247. NDIS_STATUS status = NDIS_STATUS_RESOURCES;
  248. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  249. TRACE( TL_N, TM_Tp, ("+TpProviderInitialize") );
  250. do
  251. {
  252. if ( pRequest == NULL || pAdapter == NULL )
  253. {
  254. TRACE( TL_A, TM_Tp, ("TpProviderInitialize: Invalid parameter") );
  255. status = NDIS_STATUS_TAPI_INVALPARAM;
  256. break;
  257. }
  258. //
  259. // Initialize the tapi provider context
  260. //
  261. NdisZeroMemory( &pAdapter->TapiProv, sizeof( pAdapter->TapiProv ) );
  262. //
  263. // Try to allocate resources
  264. //
  265. NdisAllocateMemoryWithTag( (PVOID) &pAdapter->TapiProv.LineTable,
  266. sizeof( LINE* ) * pAdapter->nMaxLines,
  267. MTAG_TAPIPROV );
  268. if ( pAdapter->TapiProv.LineTable == NULL )
  269. {
  270. TRACE( TL_A, TM_Tp, ("TpProviderInitialize: Could not allocate line table") );
  271. break;
  272. }
  273. NdisZeroMemory( pAdapter->TapiProv.LineTable, sizeof( LINE* ) * pAdapter->nMaxLines );
  274. pAdapter->TapiProv.hCallTable = InitializeHandleTable( pAdapter->nMaxLines * pAdapter->nCallsPerLine );
  275. if ( pAdapter->TapiProv.hCallTable == NULL )
  276. {
  277. TRACE( TL_A, TM_Tp, ("TpProviderInitialize: Could not allocate call handle table") );
  278. break;
  279. }
  280. pAdapter->TapiProv.ulTpFlags = TPBF_TapiProvInitialized;
  281. pAdapter->TapiProv.ulDeviceIDBase = pRequest->ulDeviceIDBase;
  282. //
  283. // Do referencing
  284. //
  285. ReferenceTapiProv( pAdapter, FALSE );
  286. ReferenceAdapter( pAdapter, TRUE );
  287. status = NDIS_STATUS_SUCCESS;
  288. } while ( FALSE );
  289. if ( status == NDIS_STATUS_SUCCESS )
  290. {
  291. //
  292. // Set output information
  293. //
  294. pRequest->ulNumLineDevs = pAdapter->nMaxLines;
  295. pRequest->ulProviderID = (ULONG_PTR) pAdapter->MiniportAdapterHandle;
  296. }
  297. else
  298. {
  299. //
  300. // Somethings failed, clean up
  301. //
  302. TpProviderCleanup( pAdapter );
  303. }
  304. TRACE( TL_N, TM_Tp, ("-TpProviderInitialize=$%x",status) );
  305. return status;
  306. }
  307. NDIS_STATUS
  308. TpProviderShutdown(
  309. IN ADAPTER* pAdapter,
  310. IN PNDIS_TAPI_PROVIDER_SHUTDOWN pRequest,
  311. IN BOOLEAN fNotifyNDIS
  312. )
  313. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  314. Functional Description:
  315. This request shuts down the miniport. The miniport should terminate any
  316. activities it has in progress.
  317. This operation might pend as there might be lines and call contexts still
  318. active. So this function marks the tapi provider context as close pending
  319. and calls TpCloseLine() on all active calls, and removes the reference added
  320. on the tapi provider in TpProviderInitialize().
  321. When ref count on the tapi provider context reaches 0, TpProviderShutdownComplete()
  322. will be called to clean up the tapi provider context, and remove the reference
  323. on the owning adapter.
  324. Parameters:
  325. pAdapter _ A pointer to our adapter information structure.
  326. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  327. If supplied as NULL, then we do not need to notify NDIS.
  328. typedef struct _NDIS_TAPI_PROVIDER_SHUTDOWN
  329. {
  330. IN ULONG ulRequestID;
  331. } NDIS_TAPI_PROVIDER_SHUTDOWN, *PNDIS_TAPI_PROVIDER_SHUTDOWN;
  332. fNotifyNDIS _ Indicates if NDIS needs to be notified about the completion
  333. of this operation
  334. Return Values:
  335. NDIS_STATUS_SUCCESS:
  336. Tapi provider shutdown and cleaned up succesfully.
  337. NDIS_STATUS_PENDING
  338. Shutdown operation is pending. When all shutdown operation completes
  339. owning adapter context will be dereferenced.
  340. ---------------------------------------------------------------------------*/
  341. {
  342. NDIS_STATUS status;
  343. BOOLEAN fDereferenceTapiProv = FALSE;
  344. BOOLEAN fLockAcquired = FALSE;
  345. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  346. TRACE( TL_N, TM_Tp, ("+TpProviderShutdown") );
  347. do
  348. {
  349. if ( pRequest == NULL || pAdapter == NULL )
  350. {
  351. TRACE( TL_A, TM_Tp, ("TpProviderShutdown: Invalid parameter") );
  352. status = NDIS_STATUS_TAPI_INVALPARAM;
  353. break;
  354. }
  355. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  356. fLockAcquired = TRUE;
  357. //
  358. // See if tapi provider was initialized at all
  359. //
  360. if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
  361. {
  362. //
  363. // Tapi provider was not initialized so just return
  364. //
  365. status = NDIS_STATUS_SUCCESS;
  366. break;
  367. }
  368. //
  369. // See if we can shutdown immediately
  370. //
  371. if ( pAdapter->TapiProv.lRef == 1 )
  372. {
  373. //
  374. // We are holding the only reference, so we can shutdown immediately
  375. //
  376. pAdapter->TapiProv.ulTpFlags &= ~TPBF_TapiProvInitialized;
  377. pAdapter->TapiProv.ulTpFlags |= TPBF_TapiProvShutdown;
  378. status = NDIS_STATUS_SUCCESS;
  379. }
  380. else
  381. {
  382. UINT i;
  383. //
  384. // Mark Tapi provider as shutdown pending
  385. //
  386. pAdapter->TapiProv.ulTpFlags |= TPBF_TapiProvShutdownPending;
  387. //
  388. // Mark tapi prov if the result of this operation needs to be reported to NDIS
  389. //
  390. if ( fNotifyNDIS )
  391. pAdapter->TapiProv.ulTpFlags |= TPBF_NotifyNDIS;
  392. //
  393. // Close all active lines
  394. //
  395. for ( i = 0; i < pAdapter->nMaxLines; i++)
  396. {
  397. NDIS_TAPI_CLOSE DummyRequest;
  398. LINE* pLine = (LINE*) pAdapter->TapiProv.LineTable[i];
  399. if ( pLine )
  400. {
  401. DummyRequest.hdLine = pLine->hdLine;
  402. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  403. TpCloseLine( pAdapter, &DummyRequest, FALSE );
  404. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  405. }
  406. }
  407. status = NDIS_STATUS_PENDING;
  408. }
  409. fDereferenceTapiProv = TRUE;
  410. } while ( FALSE );
  411. if ( fLockAcquired )
  412. {
  413. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  414. }
  415. if ( fDereferenceTapiProv )
  416. {
  417. DereferenceTapiProv( pAdapter );
  418. }
  419. TRACE( TL_N, TM_Tp, ("-TpProviderShutdown=$%x",status) );
  420. return status;
  421. }
  422. #define INVALID_LINE_HANDLE (HDRV_LINE) -1
  423. HDRV_LINE
  424. TpGetHdLineFromDeviceId(
  425. ADAPTER* pAdapter,
  426. ULONG ulID
  427. )
  428. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  429. Functional Description:
  430. This function is used to map a Tapi Device Id to the driver's line handle.
  431. It returns INVALID_LINE_HANDLE if it can not map the device id.
  432. REMARK:
  433. - pAdapter must not be NULL.
  434. - It must be called from one of the Tp...OidHandler() functions since
  435. this function relies on this and assumes there won't be any
  436. synchronization problems.
  437. Parameters:
  438. pAdapter _ A pointer to our adapter information structure.
  439. uldID _ Device Id that identifies a line context
  440. Return Values:
  441. Handle to the line context if device id can be mapped to a valid line context,
  442. and INVALID_LINE_HANDLE otherwise.
  443. ---------------------------------------------------------------------------*/
  444. {
  445. if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
  446. ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
  447. {
  448. if ( ( ulID < ( pAdapter->TapiProv.ulDeviceIDBase + pAdapter->nMaxLines ) ) &&
  449. ( ulID >= pAdapter->TapiProv.ulDeviceIDBase ) )
  450. {
  451. return (HDRV_LINE) ( ulID - pAdapter->TapiProv.ulDeviceIDBase );
  452. }
  453. }
  454. return INVALID_LINE_HANDLE;
  455. }
  456. LINE*
  457. TpGetLinePtrFromHdLineEx(
  458. ADAPTER* pAdapter,
  459. HDRV_LINE hdLine
  460. )
  461. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  462. Functional Description:
  463. This function is used to map a driver line handle to the line context ptr.
  464. It returns NULL if it can not map the handle. This is exactly the same as
  465. TpGetLinePtrFromHdLine function except that it doesn't check for the
  466. shutdown state.
  467. REMARK:
  468. - pAdapter must not be NULL.
  469. - It must be called from one of the Tp...OidHandler() functions since
  470. this function relies on this and assumes there won't be any
  471. synchronization problems.
  472. (Basically assumes pAdapter->lock is being held)
  473. Parameters:
  474. pAdapter _ A pointer to our adapter information structure.
  475. hdL _ Driver's line handle
  476. Return Values:
  477. Pointer to the Line context associated with the Line handle provided
  478. if mapping is succesful, and NULL otherwise.
  479. ---------------------------------------------------------------------------*/
  480. {
  481. if ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized )
  482. {
  483. if ( ( (ULONG) hdLine < (ULONG) pAdapter->nMaxLines ) )
  484. {
  485. ASSERT( pAdapter->TapiProv.LineTable != 0 );
  486. return pAdapter->TapiProv.LineTable[ (ULONG) hdLine ];
  487. }
  488. }
  489. return NULL;
  490. }
  491. LINE*
  492. TpGetLinePtrFromHdLine(
  493. ADAPTER* pAdapter,
  494. HDRV_LINE hdLine
  495. )
  496. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  497. Functional Description:
  498. This function is used to map a driver line handle to the line context ptr.
  499. It returns NULL if it can not map the handle.
  500. REMARK:
  501. - pAdapter must not be NULL.
  502. - It must be called from one of the Tp...OidHandler() functions since
  503. this function relies on this and assumes there won't be any
  504. synchronization problems.
  505. (Basically assumes pAdapter->lock is being held)
  506. Parameters:
  507. pAdapter _ A pointer to our adapter information structure.
  508. hdL _ Driver's line handle
  509. Return Values:
  510. Pointer to the Line context associated with the Line handle provided
  511. if mapping is succesful, and NULL otherwise.
  512. ---------------------------------------------------------------------------*/
  513. {
  514. if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
  515. ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
  516. {
  517. if ( ( (ULONG) hdLine < (ULONG) pAdapter->nMaxLines ) )
  518. {
  519. ASSERT( pAdapter->TapiProv.LineTable != 0 );
  520. return pAdapter->TapiProv.LineTable[ (ULONG) hdLine ];
  521. }
  522. }
  523. return NULL;
  524. }
  525. NDIS_STATUS
  526. TpOpenLine(
  527. ADAPTER* pAdapter,
  528. PNDIS_TAPI_OPEN pRequest
  529. )
  530. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  531. Functional Description:
  532. This function opens the line device whose device ID is given, returning
  533. the miniports handle for the device. The miniport must retain the
  534. Connection Wrapper's handle for the device for use in subsequent calls to
  535. the LINE_EVENT callback procedure.
  536. hdLine returned is the index to the pAdapter->TapiProv.LineTable array
  537. that holds the pointer to the new line context.
  538. Parameters:
  539. pAdapter _ A pointer to our adapter information structure.
  540. pRequest - A pointer to the NDIS_TAPI request structure for this call.
  541. typedef struct _NDIS_TAPI_OPEN
  542. {
  543. IN ULONG ulRequestID;
  544. IN ULONG ulDeviceID;
  545. IN HTAPI_LINE htLine;
  546. OUT HDRV_LINE hdLine;
  547. } NDIS_TAPI_OPEN, *PNDIS_TAPI_OPEN;
  548. Return Values:
  549. NDIS_STATUS_SUCCESS
  550. NDIS_STATUS_PENDING
  551. NDIS_STATUS_TAPI_ALLOCATED
  552. NDIS_STATUS_TAPI_INVALMEDIAMODE
  553. NDIS_STATUS_FAILURE
  554. ---------------------------------------------------------------------------*/
  555. {
  556. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  557. HDRV_LINE hdLine = INVALID_LINE_HANDLE;
  558. LINE* pLine = NULL;
  559. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  560. TRACE( TL_N, TM_Tp, ("+TpOpenLine") );
  561. do
  562. {
  563. if ( pRequest == NULL || pAdapter == NULL )
  564. {
  565. TRACE( TL_A, TM_Tp, ("TpOpenLine: Invalid parameter") );
  566. status = NDIS_STATUS_TAPI_INVALPARAM;
  567. break;
  568. }
  569. //
  570. // Map the device id to an entry in our line table
  571. //
  572. hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
  573. if ( hdLine == INVALID_LINE_HANDLE )
  574. {
  575. TRACE( TL_N, TM_Tp, ("TpOpenLine: Invalid handle supplied") );
  576. break;
  577. }
  578. //
  579. // Make sure the line is not busy already
  580. //
  581. if ( TpGetLinePtrFromHdLine( pAdapter, hdLine ) != NULL )
  582. {
  583. TRACE( TL_N, TM_Tp, ("TpOpenLine: Line is busy") );
  584. break;
  585. }
  586. //
  587. // Allocate the line context
  588. //
  589. if ( ALLOC_LINE( &pLine ) != NDIS_STATUS_SUCCESS )
  590. {
  591. TRACE( TL_A, TM_Tp, ("TpOpenLine: Could not allocate context") );
  592. break;
  593. }
  594. //
  595. // Initialize line context
  596. //
  597. NdisZeroMemory( pLine, sizeof( LINE ) );
  598. pLine->tagLine = MTAG_LINE;
  599. NdisAllocateSpinLock( &pLine->lockLine );
  600. pLine->ulLnFlags = LNBF_LineOpen;
  601. if ( pAdapter->fClientRole )
  602. {
  603. pLine->ulLnFlags |= LNBF_MakeOutgoingCalls;
  604. }
  605. //
  606. // Copy related info from adapter context
  607. //
  608. pLine->pAdapter = pAdapter;
  609. pLine->nMaxCalls = pAdapter->nCallsPerLine;
  610. InitializeListHead( &pLine->linkCalls );
  611. //
  612. // Set tapi handles
  613. //
  614. pLine->htLine = pRequest->htLine;
  615. pLine->hdLine = hdLine;
  616. //
  617. // Insert new line context to line table of tapi provider
  618. //
  619. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  620. pAdapter->TapiProv.LineTable[ (ULONG) hdLine ] = pLine;
  621. pAdapter->TapiProv.nActiveLines++;
  622. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  623. //
  624. // Do referencing
  625. //
  626. ReferenceLine( pLine, FALSE );
  627. ReferenceTapiProv( pAdapter, TRUE );
  628. status = NDIS_STATUS_SUCCESS;
  629. } while ( FALSE );
  630. if ( status == NDIS_STATUS_SUCCESS )
  631. {
  632. pRequest->hdLine = hdLine;
  633. }
  634. TRACE( TL_N, TM_Tp, ("-TpOpenLine=$%x",status) );
  635. return status;
  636. }
  637. NDIS_STATUS
  638. TpCloseLine(
  639. IN ADAPTER* pAdapter,
  640. IN PNDIS_TAPI_CLOSE pRequest,
  641. IN BOOLEAN fNotifyNDIS
  642. )
  643. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  644. Functional Description:
  645. This request closes the specified open line device after completing or
  646. aborting all outstanding calls and asynchronous requests on the device.
  647. It will remove the reference on the line context added in TpOpenLine().
  648. It will be called from 2 places:
  649. 1. When miniport receives an OID_TAPI_CLOSE.
  650. In this case, fNotifyNDIS will be set as TRUE.
  651. 2. When miniport is halting, TpProviderShutdown() will call
  652. this function for every active line context.
  653. Parameters:
  654. pAdapter _ A pointer ot our adapter information structure.
  655. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  656. typedef struct _NDIS_TAPI_CLOSE
  657. {
  658. IN ULONG ulRequestID;
  659. IN HDRV_LINE hdLine;
  660. } NDIS_TAPI_CLOSE, *PNDIS_TAPI_CLOSE;
  661. fNotifyNDIS _ Indicates if NDIS needs to be notified about the completion
  662. of this operation
  663. Return Values:
  664. NDIS_STATUS_SUCCESS: Line context destroyed succesfully.
  665. NDIS_STATUS_PENDING: Close operation is pending. When line is closed,
  666. tapi provider will be dereferenced.
  667. NDIS_STATUS_TAPI_INVALLINEHANDLE: An invalid handle was supplied.
  668. No operations performed.
  669. ---------------------------------------------------------------------------*/
  670. {
  671. LINE* pLine = NULL;
  672. BOOLEAN fLockReleased = FALSE;
  673. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  674. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  675. TRACE( TL_N, TM_Tp, ("+TpCloseLine") );
  676. do
  677. {
  678. if ( pRequest == NULL || pAdapter == NULL )
  679. {
  680. TRACE( TL_A, TM_Tp, ("TpCloseLine: Invalid parameter") );
  681. status = NDIS_STATUS_TAPI_INVALPARAM;
  682. break;
  683. }
  684. pLine = TpGetLinePtrFromHdLineEx( pAdapter, pRequest->hdLine );
  685. if ( pLine == NULL )
  686. {
  687. TRACE( TL_N, TM_Tp, ("TpCloseLine: Invalid handle supplied") );
  688. status = NDIS_STATUS_TAPI_INVALLINEHANDLE;
  689. break;
  690. }
  691. //
  692. // Remove line context from tapi providers line table
  693. // and invalidate the handle, as we do not want any more
  694. // requests on this line context.
  695. //
  696. // The active line counter will be adjusted in TpCloseLineComplete()
  697. // when we deallocate the line context.
  698. //
  699. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  700. pAdapter->TapiProv.LineTable[ (ULONG) pRequest->hdLine ] = NULL;
  701. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  702. //
  703. // Now start closing the line
  704. //
  705. NdisAcquireSpinLock( &pLine->lockLine );
  706. //
  707. // Do not accept any more incoming calls
  708. //
  709. pLine->ulLnFlags &= ~LNBF_AcceptIncomingCalls;
  710. //
  711. // Mark the line as close pending, so that we do not accept
  712. // any more requests on it
  713. //
  714. pLine->ulLnFlags |= LNBF_LineClosePending;
  715. if ( fNotifyNDIS )
  716. pLine->ulLnFlags |= LNBF_NotifyNDIS;
  717. while ( !IsListEmpty( &pLine->linkCalls ) )
  718. {
  719. CALL* pCall = NULL;
  720. NDIS_TAPI_CLOSE_CALL DummyRequest;
  721. //
  722. // Retrieve a call context from the head of active call list
  723. // and close it.
  724. //
  725. pCall = (CALL*) CONTAINING_RECORD( pLine->linkCalls.Flink,
  726. CALL,
  727. linkCalls );
  728. NdisReleaseSpinLock( &pLine->lockLine );
  729. DummyRequest.hdCall = pCall->hdCall;
  730. //
  731. // This will remove the call from the list,
  732. // so there will be a new call at the head of the list
  733. // next time we retrieve.
  734. //
  735. TpCloseCall( pAdapter, &DummyRequest, FALSE );
  736. NdisAcquireSpinLock( &pLine->lockLine );
  737. }
  738. status = NDIS_STATUS_PENDING;
  739. } while ( FALSE );
  740. if ( status == NDIS_STATUS_PENDING )
  741. {
  742. BOOLEAN fNotifyTapiOfInternalLineClose = !( pLine->ulLnFlags & LNBF_NotifyNDIS );
  743. NdisReleaseSpinLock( &pLine->lockLine );
  744. //
  745. // Check if this is an internal request to close the line,
  746. // notify TAPI if it is
  747. //
  748. if ( fNotifyTapiOfInternalLineClose )
  749. {
  750. NDIS_TAPI_EVENT TapiEvent;
  751. NdisZeroMemory( &TapiEvent, sizeof( NDIS_TAPI_EVENT ) );
  752. TapiEvent.htLine = pLine->htLine;
  753. TapiEvent.ulMsg = LINE_CLOSE;
  754. NdisMIndicateStatus( pLine->pAdapter->MiniportAdapterHandle,
  755. NDIS_STATUS_TAPI_INDICATION,
  756. &TapiEvent,
  757. sizeof( NDIS_TAPI_EVENT ) );
  758. }
  759. if ( pAdapter->TapiProv.nActiveLines == 1 )
  760. {
  761. //
  762. // We are closing the last line so notify protocol about this so
  763. // it can remove packet filters
  764. //
  765. WORKITEM* pWorkItem = NULL;
  766. PVOID Args[4];
  767. Args[0] = (PVOID) BN_ResetFiltersForCloseLine; // Is a reset filters request
  768. Args[1] = (PVOID) pLine;
  769. //
  770. // Allocate work item for reenumerating bindings
  771. //
  772. pWorkItem = AllocWorkItem( &gl_llistWorkItems,
  773. ExecBindingWorkItem,
  774. NULL,
  775. Args,
  776. BWT_workPrStartBinds );
  777. if ( pWorkItem )
  778. {
  779. //
  780. // Schedule the work item.
  781. //
  782. // Note that we need to referencing here, because we do not want TpCloseLineCopmlete()
  783. // to be called before the work item is executed.
  784. //
  785. // This reference will be removed when the work item is executed.
  786. //
  787. ReferenceLine( pLine, TRUE );
  788. ScheduleWorkItem( pWorkItem );
  789. //
  790. // In this case this request will be completed later
  791. //
  792. status = NDIS_STATUS_PENDING;
  793. }
  794. }
  795. //
  796. // Remove the reference added in line open
  797. //
  798. DereferenceLine( pLine );
  799. }
  800. TRACE( TL_N, TM_Tp, ("-TpCloseLine=$%x",status) );
  801. return status;
  802. }
  803. NDIS_STATUS
  804. TpCloseCall(
  805. IN ADAPTER* pAdapter,
  806. IN PNDIS_TAPI_CLOSE_CALL pRequest,
  807. IN BOOLEAN fNotifyNDIS
  808. )
  809. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  810. Functional Description:
  811. This function is called to close a call.
  812. It will remove one of the references added in TpMakeCall() on the call
  813. context.
  814. It will be called from 2 places:
  815. 1. When miniport receives an OID_TAPI_CLOSE_CALL.
  816. In this case, fNotifyNDIS will be set as TRUE.
  817. 2. When miniport is halting, TpCloseLine() will call
  818. this function for every active call context.
  819. Parameters:
  820. pAdapter _ A pointer to our adapter information structure.
  821. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  822. typedef struct _NDIS_TAPI_CLOSE_CALL
  823. {
  824. IN ULONG ulRequestID;
  825. IN HDRV_CALL hdCall;
  826. } NDIS_TAPI_CLOSE_CALL, *PNDIS_TAPI_CLOSE_CALL;
  827. fNotifyNDIS _ Indicates if NDIS needs to be notified about the completion
  828. of this operation
  829. Return Values:
  830. NDIS_STATUS_SUCCESS: Call is succesfully closed and resources are freed.
  831. NDIS_STATUS_PENDING: Call close is pending on active calls.
  832. When call is closed the owning line context will be
  833. dereferenced.
  834. ---------------------------------------------------------------------------*/
  835. {
  836. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  837. CALL* pCall = NULL;
  838. BOOLEAN fLockReleased = FALSE;
  839. BOOLEAN fDereferenceCall = FALSE;
  840. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  841. TRACE( TL_N, TM_Tp, ("+TpCloseCall") );
  842. do
  843. {
  844. if ( pRequest == NULL || pAdapter == NULL )
  845. {
  846. TRACE( TL_A, TM_Tp, ("TpCloseCall: Invalid parameter") );
  847. status = NDIS_STATUS_TAPI_INVALPARAM;
  848. break;
  849. }
  850. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  851. (NDIS_HANDLE) pRequest->hdCall );
  852. if ( pCall == NULL )
  853. {
  854. TRACE( TL_N, TM_Tp, ("TpCloseCall: Invalid handle supplied") );
  855. break;
  856. }
  857. //
  858. // Now start closing the call
  859. //
  860. NdisAcquireSpinLock( &pCall->lockCall );
  861. /*
  862. if ( !fNotifyNDIS )
  863. {
  864. //
  865. // Request is not coming from TAPI directly, so see if we have informed TAPI of
  866. // a new call, because if we have then we can not close the call now, we should
  867. // wait for TAPI to close it.
  868. //
  869. if ( pCall->htCall )
  870. {
  871. TRACE( TL_N, TM_Tp, ("TpCloseCall: Internal close request for a TAPI informed call, can not close now") );
  872. NdisReleaseSpinLock( &pCall->lockCall );
  873. status = NDIS_STATUS_FAILURE;
  874. break;
  875. }
  876. }
  877. */
  878. //
  879. // See if call is already closed or closing
  880. //
  881. if ( pCall->ulClFlags & CLBF_CallClosePending ||
  882. pCall->ulClFlags & CLBF_CallClosed )
  883. {
  884. TRACE( TL_N, TM_Tp, ("TpCloseCall: Close request on an already closed call") );
  885. NdisReleaseSpinLock( &pCall->lockCall );
  886. status = NDIS_STATUS_FAILURE;
  887. break;
  888. }
  889. //
  890. // Mark call if we need to notify NDIS about the completion of close
  891. //
  892. if ( fNotifyNDIS )
  893. pCall->ulClFlags |= CLBF_NotifyNDIS;
  894. //
  895. // Mark call as close pending
  896. //
  897. pCall->ulClFlags |= CLBF_CallClosePending;
  898. //
  899. // Drop the call first
  900. //
  901. NdisReleaseSpinLock( &pCall->lockCall );
  902. //
  903. // Drop will take care of unbinding and cancelling the timer
  904. //
  905. {
  906. NDIS_TAPI_DROP DummyRequest;
  907. DummyRequest.hdCall = pRequest->hdCall;
  908. TpDropCall( pAdapter, &DummyRequest, 0 );
  909. }
  910. status = NDIS_STATUS_PENDING;
  911. } while ( FALSE );
  912. if ( status == NDIS_STATUS_SUCCESS ||
  913. status == NDIS_STATUS_PENDING )
  914. {
  915. LINE* pLine = pCall->pLine;
  916. //
  917. // Remove call from line's active call list, and decrement
  918. // active call counter
  919. //
  920. NdisAcquireSpinLock( &pLine->lockLine );
  921. RemoveHeadList( pCall->linkCalls.Blink );
  922. pLine->nActiveCalls--;
  923. NdisReleaseSpinLock( &pLine->lockLine );
  924. //
  925. // We should now remove the call from the Tapi provider's call table,
  926. // and invalidate its' handle
  927. //
  928. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  929. RemoveFromHandleTable( pAdapter->TapiProv.hCallTable,
  930. (NDIS_HANDLE) pCall->hdCall );
  931. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  932. //
  933. // Remove the reference for close call
  934. //
  935. DereferenceCall( pCall );
  936. }
  937. TRACE( TL_N, TM_Tp, ("-TpCloseCall=$%x",status) );
  938. return status;
  939. }
  940. NDIS_STATUS
  941. TpDropCall(
  942. IN ADAPTER* pAdapter,
  943. IN PNDIS_TAPI_DROP pRequest,
  944. IN ULONG ulLineDisconnectMode
  945. )
  946. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  947. Functional Description:
  948. This function will be called from a couple of places:
  949. 1. If miniport receives an OID_TAPI_DROP_CALL request from TAPI.
  950. 2. When NIC for the call is unbound, it will call TpUnbindCall(),
  951. and if the call is not dropped yet, it will call TpDropCall().
  952. 3. When the call is in connect pending stage but the call needs
  953. to be dropped.
  954. 4. When session is up and call receives a PADT packet from the peer.
  955. As this is a synchronous call, we do not need an fNotifyNDIS flag.
  956. CAUTION: All locks must be released before calling this function.
  957. Parameters:
  958. pAdapter _ A pointer to our adaptert information structure.
  959. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  960. typedef struct _NDIS_TAPI_DROP
  961. {
  962. IN ULONG ulRequestID;
  963. IN HDRV_CALL hdCall;
  964. IN ULONG ulUserUserInfoSize;
  965. IN UCHAR UserUserInfo[1];
  966. } NDIS_TAPI_DROP, *PNDIS_TAPI_DROP;
  967. ulLineDisconnectMode _ Reason for dropping the call. This is reported
  968. back to TAPI in the appropriate state change
  969. notification.
  970. Return Values:
  971. NDIS_STATUS_SUCCESS: Call is succesfully dropped.
  972. ---------------------------------------------------------------------------*/
  973. {
  974. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  975. CALL* pCall = NULL;
  976. BOOLEAN fSendPADT = FALSE;
  977. BINDING* pBinding = NULL;
  978. PPPOE_PACKET* pPacket = NULL;
  979. BOOLEAN fTapiNotifiedOfNewCall = FALSE;
  980. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  981. TRACE( TL_N, TM_Tp, ("+TpDropCall") );
  982. do
  983. {
  984. if ( pRequest == NULL || pAdapter == NULL )
  985. {
  986. TRACE( TL_A, TM_Tp, ("TpDropCall: Invalid parameter") );
  987. status = NDIS_STATUS_TAPI_INVALPARAM;
  988. break;
  989. }
  990. //
  991. // Retrieve the pointer to call from the handle table
  992. //
  993. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  994. (NDIS_HANDLE) pRequest->hdCall );
  995. if ( pCall == NULL )
  996. {
  997. TRACE( TL_N, TM_Tp, ("TpDropCall: Invalid handle supplied") );
  998. break;
  999. }
  1000. NdisAcquireSpinLock( &pCall->lockCall );
  1001. //
  1002. // Make sure call is not dropped or closed previously
  1003. //
  1004. if ( pCall->ulClFlags & CLBF_CallDropped || pCall->ulClFlags & CLBF_CallClosed)
  1005. {
  1006. //
  1007. // Call already dropped, quit
  1008. //
  1009. NdisReleaseSpinLock( &pCall->lockCall );
  1010. TRACE( TL_N, TM_Tp, ("TpDropCall: Call already dropped or closed") );
  1011. break;
  1012. }
  1013. //
  1014. // Then we must be in open state either connected, or connect pending
  1015. //
  1016. ASSERT( pCall->ulClFlags & CLBF_CallOpen );
  1017. pCall->ulClFlags &= ~CLBF_CallOpen;
  1018. pCall->ulClFlags &= ~CLBF_CallConnectPending;
  1019. pCall->ulClFlags |= CLBF_CallDropped;
  1020. if ( pCall->htCall )
  1021. {
  1022. fTapiNotifiedOfNewCall = TRUE;
  1023. }
  1024. //
  1025. // Save the binding pointer as we will detach call from it soon
  1026. //
  1027. pBinding = pCall->pBinding;
  1028. if ( pCall->usSessionId && pBinding )
  1029. {
  1030. //
  1031. // Prepare a PADT packet to send if:
  1032. // - A session id is assigned to the call (which is different than fSessionUp)
  1033. // A session id is assigned to the call when the peer is informed about the session,
  1034. // however fSessionUp will be TRUE when NDISWAN is notified about the call
  1035. //
  1036. // - A binding exists to send the PADT packet
  1037. //
  1038. status = PacketInitializePADTToSend( &pPacket,
  1039. pCall->SrcAddr,
  1040. pCall->DestAddr,
  1041. pCall->usSessionId );
  1042. if ( status == NDIS_STATUS_SUCCESS )
  1043. {
  1044. //
  1045. // The following references are mandatory as in case PrSend() returns status pending,
  1046. // they will be removed by PrSendComplete()
  1047. //
  1048. ReferencePacket( pPacket );
  1049. ReferenceBinding( pBinding, TRUE );
  1050. fSendPADT = TRUE;
  1051. }
  1052. //
  1053. // Ignore the current status as this does not affect
  1054. // the status of the Drop operation.
  1055. //
  1056. status = NDIS_STATUS_SUCCESS;
  1057. }
  1058. //
  1059. // Release the lock to take care of rest of the operation
  1060. //
  1061. NdisReleaseSpinLock( &pCall->lockCall );
  1062. //
  1063. // Cancels the timer if it is set, otherwise it will not have any effect.
  1064. //
  1065. TimerQCancelItem( &gl_TimerQ, &pCall->timerTimeout );
  1066. //
  1067. // Send PADT here if we need to
  1068. //
  1069. if ( fSendPADT )
  1070. {
  1071. NDIS_STATUS SendStatus;
  1072. SendStatus = PrSend( pBinding, pPacket );
  1073. PacketFree( pPacket );
  1074. }
  1075. //
  1076. // This will unbind us from the underlying NIC context if we are bound
  1077. //
  1078. if ( pBinding )
  1079. {
  1080. PrRemoveCallFromBinding( pBinding, pCall );
  1081. }
  1082. //
  1083. // If TAPI was already notified of the call, move it to disconnected state
  1084. //
  1085. if ( fTapiNotifiedOfNewCall )
  1086. {
  1087. TpCallStateChangeHandler( pCall,
  1088. LINECALLSTATE_DISCONNECTED,
  1089. ulLineDisconnectMode );
  1090. }
  1091. //
  1092. // Remove the reference added in TpMakeCall() that corresponds
  1093. // to the drop of the call.
  1094. //
  1095. DereferenceCall( pCall );
  1096. } while ( FALSE );
  1097. TRACE( TL_N, TM_Tp, ("-TpDropCall=$%x",status) );
  1098. return status;
  1099. }
  1100. VOID
  1101. TpCloseCallComplete(
  1102. IN CALL* pCall
  1103. )
  1104. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1105. Functional Description:
  1106. This function will be called only from DereferenceCall().
  1107. It will only be called if ref count of the call drops to 0.
  1108. When this function is called, it will deallocate the call context,
  1109. and dereference the line context.
  1110. If call contexts CLBF_NotifyNDIS flag is set, then it will call
  1111. NdisMQueryInformationComplete().
  1112. Parameters:
  1113. pCall _ A pointer to the call context that will be freed.
  1114. Return Values:
  1115. None
  1116. ---------------------------------------------------------------------------*/
  1117. {
  1118. LINE* pLine = NULL;
  1119. ASSERT( VALIDATE_CALL( pCall ) );
  1120. TRACE( TL_N, TM_Tp, ("+TpCloseCallComplete") );
  1121. //
  1122. // No need to use spin locks here, as our ref count has dropped to 0, and
  1123. // we should not be getting anymore requests on this call
  1124. //
  1125. pLine = pCall->pLine;
  1126. //
  1127. // CAUTION: Give an NDIS_MAC_LINE_DOWN indication here.
  1128. // It would be better to give this at drop time, but in that case
  1129. // there is a small timing window where NdisLinkHandle will be invalid
  1130. // and although NDISWAN protects itself against invalid handles, it might
  1131. // assert in checked builds, so instead I will do it here.
  1132. //
  1133. // If problems occur with this approach, then I will do it at drop time.
  1134. //
  1135. if ( pCall->stateCall == CL_stateSessionUp )
  1136. {
  1137. NDIS_MAC_LINE_DOWN LineDownInfo;
  1138. //
  1139. // Fill-in the line down structure
  1140. //
  1141. LineDownInfo.NdisLinkContext = pCall->NdisLinkContext;
  1142. //
  1143. // Reflect the change onto the call
  1144. //
  1145. pCall->stateCall = CL_stateDisconnected;
  1146. pCall->NdisLinkContext = 0;
  1147. TRACE( TL_N, TM_Tp, ("TpCloseCallComplete: Indicate NDIS_STATUS_WAN_LINE_DOWN") );
  1148. NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
  1149. NDIS_STATUS_WAN_LINE_DOWN,
  1150. &LineDownInfo,
  1151. sizeof( NDIS_MAC_LINE_DOWN ) );
  1152. }
  1153. if ( pCall->ulClFlags & CLBF_NotifyNDIS )
  1154. {
  1155. TRACE( TL_N, TM_Tp, ("TpCloseCallComplete: Notifying NDIS") );
  1156. //
  1157. // The close call was a result of OID_TAPI_CLOSE_CALL request so complete the request.
  1158. // There is a small timing window where this call may happen before MpSetInformation()
  1159. // returns NDIS_STATUS_PENDING, but ArvindM says this is not a problem.
  1160. //
  1161. NdisMSetInformationComplete( pLine->pAdapter->MiniportAdapterHandle, NDIS_STATUS_SUCCESS );
  1162. }
  1163. //
  1164. // Clean up the call context
  1165. //
  1166. TpCallCleanup( pCall );
  1167. //
  1168. // Remove the reference on the owning line
  1169. //
  1170. DereferenceLine( pLine );
  1171. TRACE( TL_N, TM_Tp, ("-TpCloseCallComplete") );
  1172. }
  1173. VOID
  1174. TpCloseLineComplete(
  1175. IN LINE* pLine
  1176. )
  1177. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1178. Functional Description:
  1179. This function will be called to indicate that a line has been closed, and
  1180. the line context can be freed.
  1181. It will only be called from DereferenceLine() if ref count on the line context
  1182. drops to 0.
  1183. It will also remove the reference on the owning tapi provider context.
  1184. Parameters:
  1185. pLine _ A pointer to our line information structure that is closed
  1186. and ready to be deallocated.
  1187. Return Values:
  1188. None
  1189. ---------------------------------------------------------------------------*/
  1190. {
  1191. IN ADAPTER* pAdapter = NULL;
  1192. ASSERT( VALIDATE_LINE( pLine ) );
  1193. TRACE( TL_N, TM_Tp, ("+TpCloseLineComplete") );
  1194. pAdapter = pLine->pAdapter;
  1195. //
  1196. // Decrement the tapi provider's active line counter
  1197. //
  1198. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  1199. pAdapter->TapiProv.nActiveLines--;
  1200. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1201. //
  1202. // Notify NDIS if necesarry
  1203. //
  1204. if ( pLine->ulLnFlags & LNBF_NotifyNDIS )
  1205. {
  1206. TRACE( TL_N, TM_Tp, ("TpCloseLineComplete: Notifying NDIS") );
  1207. //
  1208. // Line was closed as a result of OID_TAPI_CLOSE request,
  1209. // so indicate the completion.
  1210. //
  1211. NdisMSetInformationComplete( pAdapter->MiniportAdapterHandle, NDIS_STATUS_SUCCESS );
  1212. }
  1213. //
  1214. // Clean up line context
  1215. //
  1216. TpLineCleanup( pLine );
  1217. //
  1218. // Remove the reference on the owning tapi provider
  1219. //
  1220. DereferenceTapiProv( pAdapter );
  1221. TRACE( TL_N, TM_Tp, ("-TpCloseLineComplete") );
  1222. }
  1223. VOID
  1224. TpProviderShutdownComplete(
  1225. IN ADAPTER* pAdapter
  1226. )
  1227. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1228. Functional Description:
  1229. This function will only be called from DereferenceTapiProv() if ref count
  1230. on the tapi provider object drops to 0.
  1231. It will do the necesarry clean up on the tapi provider context, and dereference
  1232. the owning adapter context.
  1233. Parameters:
  1234. pAdapter _ A pointer to our adapter information structure.
  1235. Return Values:
  1236. None
  1237. ---------------------------------------------------------------------------*/
  1238. {
  1239. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  1240. TRACE( TL_N, TM_Tp, ("+TpProviderShutdownComplete") );
  1241. //
  1242. // See if we need to notify NDIS about the completion of shut down.
  1243. //
  1244. if ( pAdapter->TapiProv.ulTpFlags & TPBF_NotifyNDIS )
  1245. {
  1246. TRACE( TL_N, TM_Tp, ("TpProviderShutdownComplete: Notifying NDIS") );
  1247. //
  1248. // Tapi was shut down as a result of OID_TAPI_PROVIDER_SHUTDOWN request,
  1249. // so indicate the completion.
  1250. //
  1251. NdisMSetInformationComplete( pAdapter->MiniportAdapterHandle, NDIS_STATUS_SUCCESS );
  1252. }
  1253. //
  1254. // Clean up tapi provider
  1255. //
  1256. TpProviderCleanup( pAdapter );
  1257. //
  1258. // Remove the reference on the owning adapter context
  1259. //
  1260. DereferenceAdapter( pAdapter );
  1261. TRACE( TL_N, TM_Tp, ("-TpProviderShutdownComplete") );
  1262. }
  1263. VOID
  1264. TpProviderCleanup(
  1265. IN ADAPTER* pAdapter
  1266. )
  1267. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1268. Functional Description:
  1269. This function will do the necesarry clean up on the tapi provider deallocating
  1270. all of its resources.
  1271. Parameters:
  1272. pAdapter _ A pointer to our adapter information structure.
  1273. Return Values:
  1274. None
  1275. ---------------------------------------------------------------------------*/
  1276. {
  1277. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  1278. TRACE( TL_N, TM_Tp, ("+TpProviderCleanup") );
  1279. if ( pAdapter )
  1280. {
  1281. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  1282. if ( pAdapter->TapiProv.LineTable )
  1283. {
  1284. NdisFreeMemory( pAdapter->TapiProv.LineTable,
  1285. sizeof( LINE* ) * pAdapter->nMaxLines,
  1286. 0 );
  1287. pAdapter->TapiProv.LineTable = NULL;
  1288. }
  1289. if ( pAdapter->TapiProv.hCallTable )
  1290. {
  1291. FreeHandleTable( pAdapter->TapiProv.hCallTable );
  1292. pAdapter->TapiProv.hCallTable = NULL;
  1293. }
  1294. NdisZeroMemory( &pAdapter->TapiProv, sizeof( pAdapter->TapiProv ) );
  1295. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1296. }
  1297. TRACE( TL_N, TM_Tp, ("-TpProviderCleanup") );
  1298. }
  1299. VOID
  1300. TpLineCleanup(
  1301. IN LINE* pLine
  1302. )
  1303. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1304. Functional Description:
  1305. This function will do the necesarry clean up on the line context deallocating
  1306. all of its resources.
  1307. Parameters:
  1308. pLine _ A pointer to our line information structure.
  1309. Return Values:
  1310. None
  1311. ---------------------------------------------------------------------------*/
  1312. {
  1313. ASSERT( VALIDATE_LINE( pLine ) );
  1314. TRACE( TL_N, TM_Tp, ("+TpLineCleanup") );
  1315. NdisFreeSpinLock( &pLine->lockLine );
  1316. FREE_LINE( pLine );
  1317. TRACE( TL_N, TM_Tp, ("-TpLineCleanup") );
  1318. }
  1319. VOID
  1320. TpCallCleanup(
  1321. IN CALL* pCall
  1322. )
  1323. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1324. Functional Description:
  1325. This function will do the necesarry clean up on the call context deallocating
  1326. all of its resources.
  1327. Parameters:
  1328. pCall _ A pointer to our call information structure.
  1329. Return Values:
  1330. None
  1331. ---------------------------------------------------------------------------*/
  1332. {
  1333. PPPOE_PACKET* pPacket = NULL;
  1334. LIST_ENTRY* pLink = NULL;
  1335. ASSERT( VALIDATE_CALL( pCall ) );
  1336. TRACE( TL_N, TM_Tp, ("+TpCallCleanup") );
  1337. NdisFreeSpinLock( &pCall->lockCall );
  1338. if ( pCall->pSendPacket )
  1339. PacketFree( pCall->pSendPacket );
  1340. while ( pCall->nReceivedPackets > 0 )
  1341. {
  1342. pLink = RemoveHeadList( &pCall->linkReceivedPackets );
  1343. pCall->nReceivedPackets--;
  1344. pPacket = (PPPOE_PACKET*) CONTAINING_RECORD( pLink, PPPOE_PACKET, linkPackets );
  1345. DereferencePacket( pPacket );
  1346. }
  1347. FREE_CALL( pCall );
  1348. TRACE( TL_N, TM_Tp, ("-TpCallCleanup") );
  1349. }
  1350. NDIS_STATUS
  1351. TpSetDefaultMediaDetection(
  1352. IN ADAPTER* pAdapter,
  1353. IN PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pRequest
  1354. )
  1355. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1356. Functional Description:
  1357. This request informs the miniport of the new set of media modes to detect
  1358. for the indicated line (replacing any previous set).
  1359. Parameters:
  1360. pAdapter _ A pointer ot our adapter information structure.
  1361. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  1362. typedef struct _NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION
  1363. {
  1364. IN ULONG ulRequestID;
  1365. IN HDRV_LINE hdLine;
  1366. IN ULONG ulMediaModes;
  1367. } NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION, *
  1368. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION;
  1369. Return Values:
  1370. NDIS_STATUS_SUCCESS
  1371. NDIS_STATUS_TAPI_INVALLINEHANDLE
  1372. ---------------------------------------------------------------------------*/
  1373. {
  1374. LINE* pLine = NULL;
  1375. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  1376. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  1377. TRACE( TL_N, TM_Tp, ("+TpSetDefaultMediaDetection") );
  1378. if ( pRequest == NULL || pAdapter == NULL )
  1379. {
  1380. TRACE( TL_A, TM_Tp, ("TpSetDefaultMediaDetection: Invalid parameter") );
  1381. TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetection=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  1382. return NDIS_STATUS_TAPI_INVALPARAM;
  1383. }
  1384. //
  1385. // Retrieve the pointer to line context
  1386. //
  1387. pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
  1388. if ( pLine == NULL )
  1389. {
  1390. TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetection=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
  1391. return NDIS_STATUS_TAPI_INVALLINEHANDLE;
  1392. }
  1393. //
  1394. // We only accept this request if we are not in client mode, and digital media
  1395. // is one of the modes proposed
  1396. //
  1397. if ( ( pRequest->ulMediaModes & LINEMEDIAMODE_DIGITALDATA ) && !pAdapter->fClientRole )
  1398. {
  1399. pLine->ulLnFlags |= LNBF_AcceptIncomingCalls;
  1400. }
  1401. else
  1402. {
  1403. pLine->ulLnFlags &= ~LNBF_AcceptIncomingCalls;
  1404. }
  1405. {
  1406. //
  1407. // Schedule a work item to reenumerate bindings
  1408. //
  1409. WORKITEM* pWorkItem = NULL;
  1410. PVOID Args[4];
  1411. Args[0] = (PVOID) BN_SetFiltersForMediaDetection; // Is a set filters request
  1412. Args[1] = (PVOID) pLine;
  1413. Args[2] = (PVOID) pRequest;
  1414. //
  1415. // Allocate work item for reenumerating bindings
  1416. //
  1417. pWorkItem = AllocWorkItem( &gl_llistWorkItems,
  1418. ExecBindingWorkItem,
  1419. NULL,
  1420. Args,
  1421. BWT_workPrStartBinds );
  1422. if ( pWorkItem )
  1423. {
  1424. //
  1425. // Schedule work item.
  1426. //
  1427. // Note that we do not need to referencing becaue we are not completing
  1428. // the query information request at this point, so nothing can go wrong
  1429. // untill it is completed, and it will be done when the work item is executed.
  1430. //
  1431. ScheduleWorkItem( pWorkItem );
  1432. //
  1433. // In this case this request will be completed later
  1434. //
  1435. status = NDIS_STATUS_PENDING;
  1436. }
  1437. }
  1438. TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetection=$%x",status) );
  1439. return status;
  1440. }
  1441. VOID
  1442. TpSetDefaultMediaDetectionComplete(
  1443. IN LINE* pLine,
  1444. IN PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pRequest
  1445. )
  1446. {
  1447. TRACE( TL_N, TM_Tp, ("+TpSetDefaultMediaDetectionComplete") );
  1448. NdisMQueryInformationComplete( pLine->pAdapter->MiniportAdapterHandle,
  1449. NDIS_STATUS_SUCCESS );
  1450. TRACE( TL_N, TM_Tp, ("-TpSetDefaultMediaDetectionComplete=$%x", NDIS_STATUS_SUCCESS) );
  1451. }
  1452. #define TAPI_EXT_VERSION 0x00010000
  1453. NDIS_STATUS
  1454. TpNegotiateExtVersion(
  1455. IN ADAPTER* pAdapter,
  1456. IN PNDIS_TAPI_NEGOTIATE_EXT_VERSION pRequest
  1457. )
  1458. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1459. Functional Description:
  1460. This request returns the highest extension version number the service
  1461. provider is willing to operate under for this device given the range of
  1462. possible extension versions.
  1463. Parameters:
  1464. pAdapter _ A pointer ot our adapter information structure.
  1465. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  1466. typedef struct _NDIS_TAPI_NEGOTIATE_EXT_VERSION
  1467. {
  1468. IN ULONG ulRequestID;
  1469. IN ULONG ulDeviceID;
  1470. IN ULONG ulLowVersion;
  1471. IN ULONG ulHighVersion;
  1472. OUT ULONG ulExtVersion;
  1473. } NDIS_TAPI_NEGOTIATE_EXT_VERSION, *PNDIS_TAPI_NEGOTIATE_EXT_VERSION;
  1474. Return Values:
  1475. NDIS_STATUS_SUCCESS
  1476. NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION
  1477. ---------------------------------------------------------------------------*/
  1478. {
  1479. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  1480. TRACE( TL_N, TM_Tp, ("+TpNegotiateExtVersion") );
  1481. if ( pRequest == NULL || pAdapter == NULL )
  1482. {
  1483. TRACE( TL_A, TM_Tp, ("TpNegotiateExtVersion: Invalid parameter") );
  1484. TRACE( TL_N, TM_Tp, ("-TpNegotiateExtVersion=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  1485. return NDIS_STATUS_TAPI_INVALPARAM;
  1486. }
  1487. //
  1488. // Make sure the miniport's version number is within the allowable
  1489. // range requested by the caller.
  1490. //
  1491. // We ignore the ulDeviceID because the version information applies
  1492. // to all devices on this adapter.
  1493. //
  1494. if ( TAPI_EXT_VERSION < pRequest->ulLowVersion ||
  1495. TAPI_EXT_VERSION > pRequest->ulHighVersion )
  1496. {
  1497. TRACE( TL_N, TM_Tp, ("-TpNegotiateExtVersion=$%x",NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION) );
  1498. return NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION;
  1499. }
  1500. //
  1501. // Looks like we're compatible, so tell the caller what we expect.
  1502. //
  1503. pRequest->ulExtVersion = TAPI_EXT_VERSION;
  1504. TRACE( TL_N, TM_Tp, ("-TpNegotiateExtVersion=$%x",NDIS_STATUS_SUCCESS) );
  1505. return NDIS_STATUS_SUCCESS;
  1506. }
  1507. NDIS_STATUS
  1508. TpGetExtensionId(
  1509. IN ADAPTER* pAdapter,
  1510. IN PNDIS_TAPI_GET_EXTENSION_ID pRequest
  1511. )
  1512. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1513. Functional Description:
  1514. This request returns the extension ID that the miniport supports for the
  1515. indicated line device.
  1516. Parameters:
  1517. pAdapter _ A pointer ot our adapter information structure.
  1518. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  1519. typedef struct _NDIS_TAPI_GET_EXTENSION_ID
  1520. {
  1521. IN ULONG ulRequestID;
  1522. IN ULONG ulDeviceID;
  1523. OUT LINE_EXTENSION_ID LineExtensionID;
  1524. } NDIS_TAPI_GET_EXTENSION_ID, *PNDIS_TAPI_GET_EXTENSION_ID;
  1525. typedef struct _LINE_EXTENSION_ID
  1526. {
  1527. ULONG ulExtensionID0;
  1528. ULONG ulExtensionID1;
  1529. ULONG ulExtensionID2;
  1530. ULONG ulExtensionID3;
  1531. } LINE_EXTENSION_ID, *PLINE_EXTENSION_ID;
  1532. Return Values:
  1533. NDIS_STATUS_SUCCESS
  1534. NDIS_STATUS_TAPI_NODRIVER
  1535. ---------------------------------------------------------------------------*/
  1536. {
  1537. HDRV_LINE hdLine = INVALID_LINE_HANDLE;
  1538. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  1539. TRACE( TL_N, TM_Tp, ("+TpGetExtensionId") );
  1540. if ( pRequest == NULL || pAdapter == NULL )
  1541. {
  1542. TRACE( TL_A, TM_Tp, ("TpGetExtensionId: Invalid parameter") );
  1543. TRACE( TL_N, TM_Tp, ("-TpGetExtensionId=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  1544. return NDIS_STATUS_TAPI_INVALPARAM;
  1545. }
  1546. //
  1547. // Retrieve the handle to line context
  1548. //
  1549. hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
  1550. if ( hdLine == INVALID_LINE_HANDLE )
  1551. {
  1552. TRACE( TL_N, TM_Tp, ("-TpGetExtensionId=$%x",NDIS_STATUS_TAPI_NODRIVER) );
  1553. return NDIS_STATUS_TAPI_NODRIVER;
  1554. }
  1555. //
  1556. // This driver does not support any extensions, so we return zeros.
  1557. //
  1558. pRequest->LineExtensionID.ulExtensionID0 = 0;
  1559. pRequest->LineExtensionID.ulExtensionID1 = 0;
  1560. pRequest->LineExtensionID.ulExtensionID2 = 0;
  1561. pRequest->LineExtensionID.ulExtensionID3 = 0;
  1562. TRACE( TL_N, TM_Tp, ("-TpGetExtensionId=$%x",NDIS_STATUS_SUCCESS) );
  1563. return NDIS_STATUS_SUCCESS;
  1564. }
  1565. NDIS_STATUS
  1566. TpGetAddressStatus(
  1567. IN ADAPTER* pAdapter,
  1568. IN PNDIS_TAPI_GET_ADDRESS_STATUS pRequest
  1569. )
  1570. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1571. Functional Description:
  1572. This request queries the specified address for its current status.
  1573. Parameters:
  1574. pAdapter _ A pointer ot our adapter information structure.
  1575. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  1576. typedef struct _NDIS_TAPI_GET_ADDRESS_STATUS
  1577. {
  1578. IN ULONG ulRequestID;
  1579. IN HDRV_LINE hdLine;
  1580. IN ULONG ulAddressID;
  1581. OUT LINE_ADDRESS_STATUS LineAddressStatus;
  1582. } NDIS_TAPI_GET_ADDRESS_STATUS, *PNDIS_TAPI_GET_ADDRESS_STATUS;
  1583. typedef struct _LINE_ADDRESS_STATUS
  1584. {
  1585. ULONG ulTotalSize;
  1586. ULONG ulNeededSize;
  1587. ULONG ulUsedSize;
  1588. ULONG ulNumInUse;
  1589. ULONG ulNumActiveCalls;
  1590. ULONG ulNumOnHoldCalls;
  1591. ULONG ulNumOnHoldPendCalls;
  1592. ULONG ulAddressFeatures;
  1593. ULONG ulNumRingsNoAnswer;
  1594. ULONG ulForwardNumEntries;
  1595. ULONG ulForwardSize;
  1596. ULONG ulForwardOffset;
  1597. ULONG ulTerminalModesSize;
  1598. ULONG ulTerminalModesOffset;
  1599. ULONG ulDevSpecificSize;
  1600. ULONG ulDevSpecificOffset;
  1601. } LINE_ADDRESS_STATUS, *PLINE_ADDRESS_STATUS;
  1602. Return Values:
  1603. NDIS_STATUS_SUCCESS
  1604. NDIS_STATUS_FAILURE
  1605. NDIS_STATUS_TAPI_INVALLINEHANDLE
  1606. NDIS_STATUS_TAPI_INVALADDRESSID
  1607. ---------------------------------------------------------------------------*/
  1608. {
  1609. LINE* pLine = NULL;
  1610. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  1611. TRACE( TL_N, TM_Tp, ("+TpGetAddressStatus") );
  1612. if ( pRequest == NULL || pAdapter == NULL )
  1613. {
  1614. TRACE( TL_A, TM_Tp, ("TpGetAddressStatus: Invalid parameter") );
  1615. TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  1616. return NDIS_STATUS_TAPI_INVALPARAM;
  1617. }
  1618. //
  1619. // Retrieve the pointer to line context
  1620. //
  1621. pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
  1622. if ( pLine == NULL )
  1623. {
  1624. TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
  1625. return NDIS_STATUS_TAPI_INVALLINEHANDLE;
  1626. }
  1627. pRequest->LineAddressStatus.ulNeededSize = sizeof( LINE_ADDRESS_STATUS );
  1628. if ( pRequest->LineAddressStatus.ulTotalSize < pRequest->LineAddressStatus.ulNeededSize )
  1629. {
  1630. TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_INVALID_LENGTH) );
  1631. return NDIS_STATUS_INVALID_LENGTH;
  1632. }
  1633. pRequest->LineAddressStatus.ulUsedSize = pRequest->LineAddressStatus.ulNeededSize;
  1634. //
  1635. // Make sure the address is within range - we only support one per line.
  1636. //
  1637. if ( pRequest->ulAddressID > 1 )
  1638. {
  1639. TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_TAPI_INVALADDRESSID) );
  1640. return NDIS_STATUS_TAPI_INVALADDRESSID;
  1641. }
  1642. //
  1643. // Return the current status information for the address
  1644. //
  1645. pRequest->LineAddressStatus.ulNumInUse = ( pLine->nActiveCalls > 0 ) ? 1 : 0;
  1646. pRequest->LineAddressStatus.ulNumActiveCalls = pLine->nActiveCalls;
  1647. pRequest->LineAddressStatus.ulAddressFeatures = ( pLine->nActiveCalls < pLine->nMaxCalls ) ?
  1648. LINEADDRFEATURE_MAKECALL :
  1649. 0;
  1650. pRequest->LineAddressStatus.ulNumRingsNoAnswer = 999;
  1651. TRACE( TL_N, TM_Tp, ("-TpGetAddressStatus=$%x",NDIS_STATUS_SUCCESS) );
  1652. return NDIS_STATUS_SUCCESS;
  1653. }
  1654. #define TAPI_DEVICECLASS_NAME "tapi/line"
  1655. #define TAPI_DEVICECLASS_ID 1
  1656. #define NDIS_DEVICECLASS_NAME "ndis"
  1657. #define NDIS_DEVICECLASS_ID 2
  1658. NDIS_STATUS
  1659. TpGetId(
  1660. IN ADAPTER* pAdapter,
  1661. IN PNDIS_TAPI_GET_ID pRequest,
  1662. IN ULONG ulRequestLength
  1663. )
  1664. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1665. Functional Description:
  1666. This request returns a device ID for the specified device class
  1667. associated with the selected line, address or call.
  1668. Currently, there are two types of this request that must be supported by WAN
  1669. NIC drivers:
  1670. 1. IN DeviceClass = "ndis" // case insensitive
  1671. IN ulSelect = LINECALLSELECT_CALL
  1672. IN hdCall = ActiveCallHandle
  1673. OUT DeviceID = ConnectionWrapperID
  1674. DeviceID should be set to the NdisLinkContext handle returned by NDISWAN in
  1675. the NDIS_MAC_LINE_UP structure for the initial NDIS_STATUS_WAN_LINE_UP
  1676. indication to establish the link.
  1677. The miniport must make the initial line-up indication to establish a link (or
  1678. open a data channel on a line) before returning from this request in order to
  1679. supply this DeviceID value.
  1680. 2. IN DeviceClass = "tapi/line" // case insensitive
  1681. IN ulSelect = LINECALLSELECT_LINE
  1682. IN hdLine = OpenLineHandle
  1683. OUT DeviceID = ulDeviceID
  1684. DeviceID will be set to the miniport-determined DeviceID associated with the
  1685. line handle.
  1686. Parameters:
  1687. pAdapter _ A pointer ot our adapter information structure.
  1688. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  1689. typedef struct _NDIS_TAPI_GET_ID
  1690. {
  1691. IN ULONG ulRequestID;
  1692. IN HDRV_LINE hdLine;
  1693. IN ULONG ulAddressID;
  1694. IN HDRV_CALL hdCall;
  1695. IN ULONG ulSelect;
  1696. IN ULONG ulDeviceClassSize;
  1697. IN ULONG ulDeviceClassOffset;
  1698. OUT VAR_STRING DeviceID;
  1699. } NDIS_TAPI_GET_ID, *PNDIS_TAPI_GET_ID;
  1700. typedef struct _VAR_STRING
  1701. {
  1702. ULONG ulTotalSize;
  1703. ULONG ulNeededSize;
  1704. ULONG ulUsedSize;
  1705. ULONG ulStringFormat;
  1706. ULONG ulStringSize;
  1707. ULONG ulStringOffset;
  1708. } VAR_STRING, *PVAR_STRING;
  1709. ulRequestLength _ Length of the request buffer
  1710. Return Values:
  1711. NDIS_STATUS_SUCCESS
  1712. NDIS_STATUS_FAILURE
  1713. NDIS_STATUS_TAPI_INVALDEVICECLASS
  1714. NDIS_STATUS_TAPI_INVALLINEHANDLE
  1715. NDIS_STATUS_TAPI_INVALADDRESSID
  1716. NDIS_STATUS_TAPI_INVALCALLHANDLE
  1717. NDIS_STATUS_TAPI_OPERATIONUNAVAIL
  1718. ---------------------------------------------------------------------------*/
  1719. {
  1720. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  1721. BOOLEAN fNotifyNDIS = FALSE;
  1722. LINE* pLine = NULL;
  1723. CALL* pCall = NULL;
  1724. UINT DeviceClass = 0;
  1725. PUCHAR IDPtr;
  1726. UINT IDLength = 0;
  1727. ULONG_PTR DeviceID;
  1728. TRACE( TL_N, TM_Tp, ("+TpGetId") );
  1729. if ( pRequest == NULL || pAdapter == NULL )
  1730. {
  1731. TRACE( TL_A, TM_Tp, ("TpGetId: Invalid parameter") );
  1732. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  1733. return NDIS_STATUS_TAPI_INVALPARAM;
  1734. }
  1735. if ( pRequest->ulDeviceClassOffset + pRequest->ulDeviceClassSize > ulRequestLength )
  1736. {
  1737. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  1738. return NDIS_STATUS_TAPI_INVALPARAM;
  1739. }
  1740. if ( pRequest->ulSelect == LINECALLSELECT_LINE )
  1741. {
  1742. if ( ( pRequest->ulDeviceClassSize == sizeof(TAPI_DEVICECLASS_NAME) ) &&
  1743. ( _strnicmp(
  1744. (PCHAR) pRequest + pRequest->ulDeviceClassOffset,
  1745. TAPI_DEVICECLASS_NAME,
  1746. pRequest->ulDeviceClassSize
  1747. ) == 0 ) )
  1748. {
  1749. DeviceClass = TAPI_DEVICECLASS_ID;
  1750. //
  1751. // Do the size check up front
  1752. //
  1753. IDLength = sizeof(DeviceID);
  1754. pRequest->DeviceID.ulNeededSize = sizeof(VAR_STRING) + IDLength;
  1755. if ( pRequest->DeviceID.ulTotalSize < pRequest->DeviceID.ulNeededSize )
  1756. {
  1757. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_INVALID_LENGTH) );
  1758. return NDIS_STATUS_INVALID_LENGTH;
  1759. }
  1760. pRequest->DeviceID.ulUsedSize = pRequest->DeviceID.ulNeededSize;
  1761. }
  1762. else // UNSUPPORTED DEVICE CLASS
  1763. {
  1764. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALDEVICECLASS) );
  1765. return NDIS_STATUS_TAPI_INVALDEVICECLASS;
  1766. }
  1767. }
  1768. else if ( pRequest->ulSelect == LINECALLSELECT_CALL )
  1769. {
  1770. if ( ( pRequest->ulDeviceClassSize == sizeof(NDIS_DEVICECLASS_NAME) ) &&
  1771. ( _strnicmp(
  1772. (PCHAR) pRequest + pRequest->ulDeviceClassOffset,
  1773. NDIS_DEVICECLASS_NAME,
  1774. pRequest->ulDeviceClassSize
  1775. ) == 0 ) )
  1776. {
  1777. DeviceClass = NDIS_DEVICECLASS_ID;
  1778. //
  1779. // Do the size check up front
  1780. //
  1781. IDLength = sizeof(DeviceID);
  1782. pRequest->DeviceID.ulNeededSize = sizeof(VAR_STRING) + IDLength;
  1783. if ( pRequest->DeviceID.ulTotalSize < pRequest->DeviceID.ulNeededSize )
  1784. {
  1785. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_INVALID_LENGTH) );
  1786. return NDIS_STATUS_INVALID_LENGTH;
  1787. }
  1788. pRequest->DeviceID.ulUsedSize = pRequest->DeviceID.ulNeededSize;
  1789. }
  1790. else // UNSUPPORTED DEVICE CLASS
  1791. {
  1792. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALDEVICECLASS) );
  1793. return NDIS_STATUS_TAPI_INVALDEVICECLASS;
  1794. }
  1795. }
  1796. //
  1797. // Find the link structure associated with the request/deviceclass.
  1798. //
  1799. if ( pRequest->ulSelect == LINECALLSELECT_LINE )
  1800. {
  1801. ASSERT( DeviceClass == TAPI_DEVICECLASS_ID );
  1802. ASSERT( IDLength == sizeof( DeviceID ) );
  1803. //
  1804. // Retrieve the pointer to line context
  1805. //
  1806. pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
  1807. if ( pLine == NULL )
  1808. {
  1809. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
  1810. return NDIS_STATUS_TAPI_INVALLINEHANDLE;
  1811. }
  1812. //
  1813. // TAPI just wants the ulDeviceID for this line.
  1814. //
  1815. DeviceID = (ULONG) pLine->hdLine + pAdapter->TapiProv.ulDeviceIDBase ;
  1816. IDPtr = (PUCHAR) &DeviceID;
  1817. }
  1818. else if ( pRequest->ulSelect == LINECALLSELECT_ADDRESS )
  1819. {
  1820. //
  1821. // Retrieve the pointer to line context
  1822. //
  1823. pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
  1824. if ( pLine == NULL )
  1825. {
  1826. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
  1827. return NDIS_STATUS_TAPI_INVALLINEHANDLE;
  1828. }
  1829. if ( pRequest->ulAddressID > 1 )
  1830. {
  1831. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALADDRESSID) );
  1832. return NDIS_STATUS_TAPI_INVALADDRESSID;
  1833. }
  1834. //
  1835. // Currently, there is no defined return value for this case...
  1836. // This is just a place holder for future extensions.
  1837. //
  1838. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALDEVICECLASS) );
  1839. return NDIS_STATUS_TAPI_INVALDEVICECLASS;
  1840. }
  1841. else if ( pRequest->ulSelect == LINECALLSELECT_CALL )
  1842. {
  1843. BOOLEAN fCallReferenced = FALSE;
  1844. ASSERT( DeviceClass == NDIS_DEVICECLASS_ID );
  1845. ASSERT( IDLength == sizeof( DeviceID ) );
  1846. //
  1847. // Retrieve the pointer to call context
  1848. //
  1849. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  1850. (NDIS_HANDLE) pRequest->hdCall );
  1851. if ( pCall == NULL )
  1852. {
  1853. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_TAPI_INVALLINEHANDLE) );
  1854. return NDIS_STATUS_TAPI_INVALLINEHANDLE;
  1855. }
  1856. //
  1857. // We can only return this if we have a valid NdisLinkContext,
  1858. // and if our session is up, then our link handle must be valid
  1859. //
  1860. NdisAcquireSpinLock( &pCall->lockCall );
  1861. if ( pCall->ulTapiCallState == LINECALLSTATE_CONNECTED )
  1862. {
  1863. //
  1864. // Give a line-up indication to NDISWAN and obtain its handle
  1865. //
  1866. NDIS_MAC_LINE_UP LineUpInfo;
  1867. //
  1868. // Fill-in the line up structure
  1869. //
  1870. NdisZeroMemory( &LineUpInfo, sizeof( LineUpInfo ) );
  1871. LineUpInfo.LinkSpeed = pCall->ulSpeed;
  1872. LineUpInfo.Quality = NdisWanErrorControl;
  1873. LineUpInfo.SendWindow = 0;
  1874. LineUpInfo.ConnectionWrapperID = (NDIS_HANDLE) pCall->htCall;
  1875. LineUpInfo.NdisLinkHandle = (NDIS_HANDLE) pCall->hdCall;
  1876. LineUpInfo.NdisLinkContext = 0;
  1877. //
  1878. // Reference the call once and deref it just after indication of status
  1879. // to NDISWAN
  1880. //
  1881. ReferenceCall( pCall, FALSE );
  1882. fCallReferenced = TRUE;
  1883. NdisReleaseSpinLock( &pCall->lockCall );
  1884. TRACE( TL_N, TM_Tp, ("TpGetId: Indicate NDIS_STATUS_WAN_LINE_UP") );
  1885. NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
  1886. NDIS_STATUS_WAN_LINE_UP,
  1887. &LineUpInfo,
  1888. sizeof( NDIS_MAC_LINE_UP ) );
  1889. NdisAcquireSpinLock( &pCall->lockCall );
  1890. //
  1891. // Set state to indicate that session is established
  1892. //
  1893. pCall->stateCall = CL_stateSessionUp;
  1894. //
  1895. // Set link context obtained from NDISWAN on the call context
  1896. //
  1897. pCall->NdisLinkContext = LineUpInfo.NdisLinkContext;
  1898. DeviceID = (ULONG_PTR) pCall->NdisLinkContext;
  1899. IDPtr = (PUCHAR) &DeviceID;
  1900. //
  1901. // Since the session is up, schedule the MpIndicateReceivedPackets() handler
  1902. //
  1903. MpScheduleIndicateReceivedPacketsHandler( pCall );
  1904. status = NDIS_STATUS_SUCCESS;
  1905. }
  1906. else
  1907. {
  1908. status = NDIS_STATUS_TAPI_OPERATIONUNAVAIL;
  1909. }
  1910. NdisReleaseSpinLock( &pCall->lockCall );
  1911. if ( fCallReferenced )
  1912. {
  1913. DereferenceCall( pCall );
  1914. }
  1915. }
  1916. else // UNSUPPORTED SELECT REQUEST
  1917. {
  1918. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",NDIS_STATUS_FAILURE) );
  1919. return NDIS_STATUS_FAILURE;
  1920. }
  1921. if ( status == NDIS_STATUS_SUCCESS )
  1922. {
  1923. //
  1924. // Now we need to place the device ID.
  1925. //
  1926. pRequest->DeviceID.ulStringFormat = STRINGFORMAT_BINARY;
  1927. pRequest->DeviceID.ulStringSize = IDLength;
  1928. pRequest->DeviceID.ulStringOffset = sizeof(VAR_STRING);
  1929. NdisMoveMemory(
  1930. (PCHAR) &pRequest->DeviceID + sizeof(VAR_STRING),
  1931. IDPtr,
  1932. IDLength
  1933. );
  1934. }
  1935. if ( fNotifyNDIS )
  1936. {
  1937. TRACE( TL_N, TM_Tp, ("TpGetId:Completing delayed request") );
  1938. NdisMQueryInformationComplete( pCall->pLine->pAdapter->MiniportAdapterHandle, status );
  1939. }
  1940. TRACE( TL_N, TM_Tp, ("-TpGetId=$%x",status) );
  1941. return status;
  1942. }
  1943. #define TAPI_PROVIDER_STRING "VPN\0RASPPPOE"
  1944. #define TAPI_LINE_NAME "RAS PPPoE Line"
  1945. #define TAPI_LINE_NUM "0000"
  1946. NDIS_STATUS
  1947. TpGetDevCaps(
  1948. IN ADAPTER* pAdapter,
  1949. IN PNDIS_TAPI_GET_DEV_CAPS pRequest
  1950. )
  1951. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1952. Functional Description:
  1953. This request queries a specified line device to determine its telephony
  1954. capabilities. The returned information is valid for all addresses on the
  1955. line device.
  1956. Parameters:
  1957. pAdapter _ A pointer ot our adapter information structure.
  1958. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  1959. typedef struct _NDIS_TAPI_GET_DEV_CAPS
  1960. {
  1961. IN ULONG ulRequestID;
  1962. IN ULONG ulDeviceID;
  1963. IN ULONG ulExtVersion;
  1964. OUT LINE_DEV_CAPS LineDevCaps;
  1965. } NDIS_TAPI_GET_DEV_CAPS, *PNDIS_TAPI_GET_DEV_CAPS;
  1966. typedef struct _LINE_DEV_CAPS
  1967. {
  1968. ULONG ulTotalSize;
  1969. ULONG ulNeededSize;
  1970. ULONG ulUsedSize;
  1971. ULONG ulProviderInfoSize;
  1972. ULONG ulProviderInfoOffset;
  1973. ULONG ulSwitchInfoSize;
  1974. ULONG ulSwitchInfoOffset;
  1975. ULONG ulPermanentLineID;
  1976. ULONG ulLineNameSize;
  1977. ULONG ulLineNameOffset;
  1978. ULONG ulStringFormat;
  1979. ULONG ulAddressModes;
  1980. ULONG ulNumAddresses;
  1981. ULONG ulBearerModes;
  1982. ULONG ulMaxRate;
  1983. ULONG ulMediaModes;
  1984. ULONG ulGenerateToneModes;
  1985. ULONG ulGenerateToneMaxNumFreq;
  1986. ULONG ulGenerateDigitModes;
  1987. ULONG ulMonitorToneMaxNumFreq;
  1988. ULONG ulMonitorToneMaxNumEntries;
  1989. ULONG ulMonitorDigitModes;
  1990. ULONG ulGatherDigitsMinTimeout;
  1991. ULONG ulGatherDigitsMaxTimeout;
  1992. ULONG ulMedCtlDigitMaxListSize;
  1993. ULONG ulMedCtlMediaMaxListSize;
  1994. ULONG ulMedCtlToneMaxListSize;
  1995. ULONG ulMedCtlCallStateMaxListSize;
  1996. ULONG ulDevCapFlags;
  1997. ULONG ulMaxNumActiveCalls;
  1998. ULONG ulAnswerMode;
  1999. ULONG ulRingModes;
  2000. ULONG ulLineStates;
  2001. ULONG ulUUIAcceptSize;
  2002. ULONG ulUUIAnswerSize;
  2003. ULONG ulUUIMakeCallSize;
  2004. ULONG ulUUIDropSize;
  2005. ULONG ulUUISendUserUserInfoSize;
  2006. ULONG ulUUICallInfoSize;
  2007. LINE_DIAL_PARAMS MinDialParams;
  2008. LINE_DIAL_PARAMS MaxDialParams;
  2009. LINE_DIAL_PARAMS DefaultDialParams;
  2010. ULONG ulNumTerminals;
  2011. ULONG ulTerminalCapsSize;
  2012. ULONG ulTerminalCapsOffset;
  2013. ULONG ulTerminalTextEntrySize;
  2014. ULONG ulTerminalTextSize;
  2015. ULONG ulTerminalTextOffset;
  2016. ULONG ulDevSpecificSize;
  2017. ULONG ulDevSpecificOffset;
  2018. } LINE_DEV_CAPS, *PLINE_DEV_CAPS;
  2019. typedef struct _LINE_DIAL_PARAMS
  2020. {
  2021. ULONG ulDialPause;
  2022. ULONG ulDialSpeed;
  2023. ULONG ulDigitDuration;
  2024. ULONG ulWaitForDialtone;
  2025. } LINE_DIAL_PARAMS, *PLINE_DIAL_PARAMS;
  2026. Return Values:
  2027. NDIS_STATUS_SUCCESS
  2028. NDIS_STATUS_TAPI_NODRIVER
  2029. ---------------------------------------------------------------------------*/
  2030. {
  2031. HDRV_LINE hdLine = INVALID_LINE_HANDLE;
  2032. CHAR szTapiLineNum[] = TAPI_LINE_NUM;
  2033. CHAR *pBuf = NULL;
  2034. ULONG ulDeviceId;
  2035. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  2036. TRACE( TL_N, TM_Tp, ("+TpGetDevCaps") );
  2037. if ( pRequest == NULL || pAdapter == NULL )
  2038. {
  2039. TRACE( TL_A, TM_Tp, ("TpGetDevCaps: Invalid parameter") );
  2040. TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  2041. return NDIS_STATUS_TAPI_INVALPARAM;
  2042. }
  2043. //
  2044. // Retrieve the handle to line context
  2045. //
  2046. hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
  2047. if ( hdLine == INVALID_LINE_HANDLE )
  2048. {
  2049. TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_TAPI_NODRIVER) );
  2050. return NDIS_STATUS_TAPI_NODRIVER;
  2051. }
  2052. pRequest->LineDevCaps.ulNeededSize = sizeof( LINE_DEV_CAPS ) +
  2053. sizeof( TAPI_PROVIDER_STRING ) +
  2054. ( sizeof( TAPI_LINE_NAME ) - 1 ) +
  2055. sizeof( TAPI_LINE_NUM );
  2056. if ( pRequest->LineDevCaps.ulTotalSize < pRequest->LineDevCaps.ulNeededSize )
  2057. {
  2058. TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_INVALID_LENGTH) );
  2059. return NDIS_STATUS_INVALID_LENGTH;
  2060. }
  2061. pRequest->LineDevCaps.ulUsedSize = pRequest->LineDevCaps.ulNeededSize;
  2062. pRequest->LineDevCaps.ulAddressModes = LINEADDRESSMODE_ADDRESSID |
  2063. LINEADDRESSMODE_DIALABLEADDR;
  2064. pRequest->LineDevCaps.ulNumAddresses = 1;
  2065. pRequest->LineDevCaps.ulBearerModes = LINEBEARERMODE_DATA;
  2066. pRequest->LineDevCaps.ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
  2067. pRequest->LineDevCaps.ulMaxNumActiveCalls = pAdapter->nCallsPerLine;
  2068. pRequest->LineDevCaps.ulAnswerMode = LINEANSWERMODE_DROP;
  2069. pRequest->LineDevCaps.ulRingModes = 1;
  2070. pRequest->LineDevCaps.ulPermanentLineID = pRequest->ulDeviceID;
  2071. pRequest->LineDevCaps.ulMaxRate = 0;
  2072. pRequest->LineDevCaps.ulMediaModes = LINEMEDIAMODE_DIGITALDATA;
  2073. //
  2074. // Insert the provider string and enumerated line name into line dev caps
  2075. //
  2076. pRequest->LineDevCaps.ulStringFormat = STRINGFORMAT_ASCII;
  2077. {
  2078. INT i;
  2079. //
  2080. // Tack on the ProviderString to the end of the LineDevCaps structure
  2081. //
  2082. pRequest->LineDevCaps.ulProviderInfoSize = sizeof( TAPI_PROVIDER_STRING );
  2083. pRequest->LineDevCaps.ulProviderInfoOffset = sizeof( pRequest->LineDevCaps );
  2084. pBuf = ( (PUCHAR) &pRequest->LineDevCaps ) + pRequest->LineDevCaps.ulProviderInfoOffset;
  2085. NdisMoveMemory( pBuf , TAPI_PROVIDER_STRING, sizeof( TAPI_PROVIDER_STRING ) );
  2086. //
  2087. // Tack on the LineName after the ProviderString
  2088. //
  2089. pRequest->LineDevCaps.ulLineNameSize = ( sizeof( TAPI_LINE_NAME ) - 1 ) + sizeof( TAPI_LINE_NUM );
  2090. pRequest->LineDevCaps.ulLineNameOffset = pRequest->LineDevCaps.ulProviderInfoOffset +
  2091. pRequest->LineDevCaps.ulProviderInfoSize;
  2092. pBuf = ( (PUCHAR) &pRequest->LineDevCaps ) + pRequest->LineDevCaps.ulLineNameOffset;
  2093. NdisMoveMemory( pBuf , TAPI_LINE_NAME, sizeof( TAPI_LINE_NAME ) );
  2094. //
  2095. // Tack on the line enumeration index at the end of the LineName
  2096. //
  2097. ulDeviceId = (ULONG) hdLine;
  2098. //
  2099. // Subtract 2: 1 for '\0' and 1 to adjust for array indexing
  2100. //
  2101. i = ( sizeof( TAPI_LINE_NUM ) / sizeof( CHAR ) ) - 2;
  2102. while ( i >= 0 && ( ulDeviceId > 0 ) )
  2103. {
  2104. szTapiLineNum[i] = (UCHAR)( ( ulDeviceId % 10 ) + '0' );
  2105. ulDeviceId /= 10;
  2106. i--;
  2107. }
  2108. pBuf += ( sizeof( TAPI_LINE_NAME ) - 1 );
  2109. NdisMoveMemory( pBuf, szTapiLineNum, sizeof( TAPI_LINE_NUM ) );
  2110. }
  2111. TRACE( TL_N, TM_Tp, ("-TpGetDevCaps=$%x",NDIS_STATUS_SUCCESS) );
  2112. return NDIS_STATUS_SUCCESS;
  2113. }
  2114. NDIS_STATUS
  2115. TpGetCallStatus(
  2116. IN ADAPTER* pAdapter,
  2117. IN PNDIS_TAPI_GET_CALL_STATUS pRequest
  2118. )
  2119. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2120. Functional Description:
  2121. This request returns detailed information about the specified call.
  2122. Parameters:
  2123. pAdapter _ A pointer ot our adapter information structure.
  2124. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  2125. typedef struct _NDIS_TAPI_GET_CALL_STATUS
  2126. {
  2127. IN ULONG ulRequestID;
  2128. IN HDRV_CALL hdCall;
  2129. OUT LINE_CALL_STATUS LineCallStatus;
  2130. } NDIS_TAPI_GET_CALL_STATUS, *PNDIS_TAPI_GET_CALL_STATUS;
  2131. typedef struct _LINE_CALL_STATUS
  2132. {
  2133. ULONG ulTotalSize;
  2134. ULONG ulNeededSize;
  2135. ULONG ulUsedSize;
  2136. ULONG ulCallState;
  2137. ULONG ulCallStateMode;
  2138. ULONG ulCallPrivilege;
  2139. ULONG ulCallFeatures;
  2140. ULONG ulDevSpecificSize;
  2141. ULONG ulDevSpecificOffset;
  2142. } LINE_CALL_STATUS, *PLINE_CALL_STATUS;
  2143. Return Values:
  2144. NDIS_STATUS_SUCCESS
  2145. NDIS_STATUS_FAILURE
  2146. NDIS_STATUS_TAPI_INVALCALLHANDLE
  2147. ---------------------------------------------------------------------------*/
  2148. {
  2149. CALL* pCall = NULL;
  2150. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  2151. TRACE( TL_N, TM_Tp, ("+TpGetCallStatus") );
  2152. if ( pRequest == NULL || pAdapter == NULL )
  2153. {
  2154. TRACE( TL_A, TM_Tp, ("TpGetCallStatus: Invalid parameter") );
  2155. TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  2156. return NDIS_STATUS_TAPI_INVALPARAM;
  2157. }
  2158. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  2159. (NDIS_HANDLE) pRequest->hdCall );
  2160. if ( pCall == NULL )
  2161. {
  2162. TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_TAPI_INVALCALLHANDLE) );
  2163. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  2164. }
  2165. pRequest->LineCallStatus.ulNeededSize = sizeof( LINE_CALL_STATUS );
  2166. if ( pRequest->LineCallStatus.ulTotalSize < pRequest->LineCallStatus.ulNeededSize )
  2167. {
  2168. TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_INVALID_LENGTH) );
  2169. return NDIS_STATUS_INVALID_LENGTH;
  2170. }
  2171. pRequest->LineCallStatus.ulUsedSize = pRequest->LineCallStatus.ulNeededSize;
  2172. pRequest->LineCallStatus.ulCallFeatures = LINECALLFEATURE_ANSWER | LINECALLFEATURE_DROP;
  2173. pRequest->LineCallStatus.ulCallPrivilege = LINECALLPRIVILEGE_OWNER;
  2174. pRequest->LineCallStatus.ulCallState = pCall->ulTapiCallState;
  2175. switch ( pRequest->LineCallStatus.ulCallState )
  2176. {
  2177. case LINECALLSTATE_DIALTONE:
  2178. pRequest->LineCallStatus.ulCallStateMode = LINEDIALTONEMODE_NORMAL;
  2179. break;
  2180. case LINECALLSTATE_BUSY:
  2181. pRequest->LineCallStatus.ulCallStateMode = LINEBUSYMODE_STATION;
  2182. break;
  2183. case LINECALLSTATE_DISCONNECTED:
  2184. pRequest->LineCallStatus.ulCallStateMode = LINEDISCONNECTMODE_UNKNOWN;
  2185. break;
  2186. default:
  2187. break;
  2188. }
  2189. TRACE( TL_N, TM_Tp, ("-TpGetCallStatus=$%x",NDIS_STATUS_SUCCESS) );
  2190. return NDIS_STATUS_SUCCESS;
  2191. }
  2192. //
  2193. // As we return the MAC addresses for caller and called station id's
  2194. // we set their size as 7 although a MAC address occupies 6 bytes.
  2195. // This is because TAPI overwrites the last bytes we return in these
  2196. // strings with a NULL character destroying the vaulable data.
  2197. // See bug: 313295
  2198. //
  2199. #define TAPI_STATION_ID_SIZE ( 7 * sizeof( CHAR ) )
  2200. NDIS_STATUS
  2201. TpGetCallInfo(
  2202. IN ADAPTER* pAdapter,
  2203. IN PNDIS_TAPI_GET_CALL_INFO pRequest
  2204. )
  2205. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2206. Functional Description:
  2207. This request returns detailed information about the specified call.
  2208. Parameters:
  2209. pAdapter _ A pointer to our adapter information structure.
  2210. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  2211. typedef struct _NDIS_TAPI_GET_CALL_INFO
  2212. {
  2213. IN ULONG ulRequestID;
  2214. IN HDRV_CALL hdCall;
  2215. OUT LINE_CALL_INFO LineCallInfo;
  2216. } NDIS_TAPI_GET_CALL_INFO, *PNDIS_TAPI_GET_CALL_INFO;
  2217. typedef struct _LINE_CALL_INFO
  2218. {
  2219. ULONG ulTotalSize;
  2220. ULONG ulNeededSize;
  2221. ULONG ulUsedSize;
  2222. ULONG hLine;
  2223. ULONG ulLineDeviceID;
  2224. ULONG ulAddressID;
  2225. ULONG ulBearerMode;
  2226. ULONG ulRate;
  2227. ULONG ulMediaMode;
  2228. ULONG ulAppSpecific;
  2229. ULONG ulCallID;
  2230. ULONG ulRelatedCallID;
  2231. ULONG ulCallParamFlags;
  2232. ULONG ulCallStates;
  2233. ULONG ulMonitorDigitModes;
  2234. ULONG ulMonitorMediaModes;
  2235. LINE_DIAL_PARAMS DialParams;
  2236. ULONG ulOrigin;
  2237. ULONG ulReason;
  2238. ULONG ulCompletionID;
  2239. ULONG ulNumOwners;
  2240. ULONG ulNumMonitors;
  2241. ULONG ulCountryCode;
  2242. ULONG ulTrunk;
  2243. ULONG ulCallerIDFlags;
  2244. ULONG ulCallerIDSize;
  2245. ULONG ulCallerIDOffset;
  2246. ULONG ulCallerIDNameSize;
  2247. ULONG ulCallerIDNameOffset;
  2248. ULONG ulCalledIDFlags;
  2249. ULONG ulCalledIDSize;
  2250. ULONG ulCalledIDOffset;
  2251. ULONG ulCalledIDNameSize;
  2252. ULONG ulCalledIDNameOffset;
  2253. ULONG ulConnectedIDFlags;
  2254. ULONG ulConnectedIDSize;
  2255. ULONG ulConnectedIDOffset;
  2256. ULONG ulConnectedIDNameSize;
  2257. ULONG ulConnectedIDNameOffset;
  2258. ULONG ulRedirectionIDFlags;
  2259. ULONG ulRedirectionIDSize;
  2260. ULONG ulRedirectionIDOffset;
  2261. ULONG ulRedirectionIDNameSize;
  2262. ULONG ulRedirectionIDNameOffset;
  2263. ULONG ulRedirectingIDFlags;
  2264. ULONG ulRedirectingIDSize;
  2265. ULONG ulRedirectingIDOffset;
  2266. ULONG ulRedirectingIDNameSize;
  2267. ULONG ulRedirectingIDNameOffset;
  2268. ULONG ulAppNameSize;
  2269. ULONG ulAppNameOffset;
  2270. ULONG ulDisplayableAddressSize;
  2271. ULONG ulDisplayableAddressOffset;
  2272. ULONG ulCalledPartySize;
  2273. ULONG ulCalledPartyOffset;
  2274. ULONG ulCommentSize;
  2275. ULONG ulCommentOffset;
  2276. ULONG ulDisplaySize;
  2277. ULONG ulDisplayOffset;
  2278. ULONG ulUserUserInfoSize;
  2279. ULONG ulUserUserInfoOffset;
  2280. ULONG ulHighLevelCompSize;
  2281. ULONG ulHighLevelCompOffset;
  2282. ULONG ulLowLevelCompSize;
  2283. ULONG ulLowLevelCompOffset;
  2284. ULONG ulChargingInfoSize;
  2285. ULONG ulChargingInfoOffset;
  2286. ULONG ulTerminalModesSize;
  2287. ULONG ulTerminalModesOffset;
  2288. ULONG ulDevSpecificSize;
  2289. ULONG ulDevSpecificOffset;
  2290. } LINE_CALL_INFO, *PLINE_CALL_INFO;
  2291. typedef struct _LINE_DIAL_PARAMS
  2292. {
  2293. ULONG ulDialPause;
  2294. ULONG ulDialSpeed;
  2295. ULONG ulDigitDuration;
  2296. ULONG ulWaitForDialtone;
  2297. } LINE_DIAL_PARAMS, *PLINE_DIAL_PARAMS;
  2298. Return Values:
  2299. NDIS_STATUS_SUCCESS
  2300. NDIS_STATUS_FAILURE
  2301. NDIS_STATUS_TAPI_INVALCALLHANDLE
  2302. ---------------------------------------------------------------------------*/
  2303. {
  2304. CALL* pCall = NULL;
  2305. PLINE_CALL_INFO pLineCallInfo = NULL;
  2306. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  2307. TRACE( TL_N, TM_Tp, ("+TpGetCallInfo") );
  2308. if ( pRequest == NULL || pAdapter == NULL )
  2309. {
  2310. TRACE( TL_A, TM_Tp, ("TpGetCallInfo: Invalid parameter") );
  2311. TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  2312. return NDIS_STATUS_TAPI_INVALPARAM;
  2313. }
  2314. pLineCallInfo = &pRequest->LineCallInfo;
  2315. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  2316. (NDIS_HANDLE) pRequest->hdCall );
  2317. if ( pCall == NULL )
  2318. {
  2319. TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_TAPI_INVALCALLHANDLE) );
  2320. return NDIS_STATUS_TAPI_INVALCALLHANDLE;
  2321. }
  2322. pLineCallInfo->ulNeededSize = sizeof( LINE_CALL_INFO ) +
  2323. TAPI_STATION_ID_SIZE +
  2324. TAPI_STATION_ID_SIZE;
  2325. if ( pLineCallInfo->ulTotalSize < pLineCallInfo->ulNeededSize )
  2326. {
  2327. TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_INVALID_LENGTH) );
  2328. return NDIS_STATUS_INVALID_LENGTH;
  2329. }
  2330. pLineCallInfo->ulUsedSize = pLineCallInfo->ulNeededSize;
  2331. pLineCallInfo->ulLineDeviceID = (ULONG) pCall->pLine->hdLine +
  2332. pCall->pLine->pAdapter->TapiProv.ulDeviceIDBase;
  2333. pLineCallInfo->ulAddressID = 0;
  2334. pLineCallInfo->ulBearerMode = LINEBEARERMODE_DATA;
  2335. pLineCallInfo->ulRate = pCall->ulSpeed;
  2336. pLineCallInfo->ulMediaMode = LINEMEDIAMODE_DIGITALDATA;
  2337. pLineCallInfo->ulCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  2338. pLineCallInfo->ulCallStates = TAPI_LINECALLSTATES_SUPPORTED;
  2339. pLineCallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL;
  2340. pLineCallInfo->ulCallerIDSize = 0;
  2341. pLineCallInfo->ulCalledIDOffset = 0;
  2342. pLineCallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL;
  2343. pLineCallInfo->ulCalledIDSize = 0;
  2344. //
  2345. // Set the caller and called station id information for both
  2346. // incoming and outgoing calls.
  2347. //
  2348. {
  2349. CHAR *pBuf = NULL;
  2350. //
  2351. // Copy the caller id information
  2352. //
  2353. pLineCallInfo->ulCallerIDFlags = LINECALLPARTYID_ADDRESS;
  2354. pLineCallInfo->ulCallerIDSize = TAPI_STATION_ID_SIZE;
  2355. pLineCallInfo->ulCallerIDOffset = sizeof(LINE_CALL_INFO);
  2356. pBuf = ( (PUCHAR) pLineCallInfo ) + pLineCallInfo->ulCallerIDOffset;
  2357. NdisMoveMemory( pBuf, pCall->DestAddr, TAPI_STATION_ID_SIZE - 1 );
  2358. //
  2359. // Copy the called id information
  2360. //
  2361. pLineCallInfo->ulCalledIDFlags = LINECALLPARTYID_ADDRESS;
  2362. pLineCallInfo->ulCalledIDSize = TAPI_STATION_ID_SIZE;
  2363. pLineCallInfo->ulCalledIDOffset = pLineCallInfo->ulCallerIDOffset +
  2364. pLineCallInfo->ulCallerIDSize;
  2365. pBuf = ( (PUCHAR) pLineCallInfo ) + pLineCallInfo->ulCalledIDOffset;
  2366. NdisMoveMemory( pBuf, pCall->SrcAddr, TAPI_STATION_ID_SIZE - 1 );
  2367. pLineCallInfo->ulUsedSize = pLineCallInfo->ulNeededSize;
  2368. }
  2369. TRACE( TL_N, TM_Tp, ("-TpGetCallInfo=$%x",NDIS_STATUS_SUCCESS) );
  2370. return NDIS_STATUS_SUCCESS;
  2371. }
  2372. #define TAPI_LINE_ADDR_STRING "PPPoE VPN"
  2373. NDIS_STATUS
  2374. TpGetAddressCaps(
  2375. IN ADAPTER* pAdapter,
  2376. PNDIS_TAPI_GET_ADDRESS_CAPS pRequest
  2377. )
  2378. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2379. Functional Description:
  2380. This request queries the specified address on the specified line device
  2381. to determine its telephony capabilities.
  2382. Parameters:
  2383. pAdapter _ A pointer ot our adapter information structure.
  2384. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  2385. typedef struct _NDIS_TAPI_GET_ADDRESS_CAPS
  2386. {
  2387. IN ULONG ulRequestID;
  2388. IN ULONG ulDeviceID;
  2389. IN ULONG ulAddressID;
  2390. IN ULONG ulExtVersion;
  2391. OUT LINE_ADDRESS_CAPS LineAddressCaps;
  2392. } NDIS_TAPI_GET_ADDRESS_CAPS, *PNDIS_TAPI_GET_ADDRESS_CAPS;
  2393. typedef struct _LINE_ADDRESS_CAPS
  2394. {
  2395. ULONG ulTotalSize;
  2396. ULONG ulNeededSize;
  2397. ULONG ulUsedSize;
  2398. ULONG ulLineDeviceID;
  2399. ULONG ulAddressSize;
  2400. ULONG ulAddressOffset;
  2401. ULONG ulDevSpecificSize;
  2402. ULONG ulDevSpecificOffset;
  2403. ULONG ulAddressSharing;
  2404. ULONG ulAddressStates;
  2405. ULONG ulCallInfoStates;
  2406. ULONG ulCallerIDFlags;
  2407. ULONG ulCalledIDFlags;
  2408. ULONG ulConnectedIDFlags;
  2409. ULONG ulRedirectionIDFlags;
  2410. ULONG ulRedirectingIDFlags;
  2411. ULONG ulCallStates;
  2412. ULONG ulDialToneModes;
  2413. ULONG ulBusyModes;
  2414. ULONG ulSpecialInfo;
  2415. ULONG ulDisconnectModes;
  2416. ULONG ulMaxNumActiveCalls;
  2417. ULONG ulMaxNumOnHoldCalls;
  2418. ULONG ulMaxNumOnHoldPendingCalls;
  2419. ULONG ulMaxNumConference;
  2420. ULONG ulMaxNumTransConf;
  2421. ULONG ulAddrCapFlags;
  2422. ULONG ulCallFeatures;
  2423. ULONG ulRemoveFromConfCaps;
  2424. ULONG ulRemoveFromConfState;
  2425. ULONG ulTransferModes;
  2426. ULONG ulForwardModes;
  2427. ULONG ulMaxForwardEntries;
  2428. ULONG ulMaxSpecificEntries;
  2429. ULONG ulMinFwdNumRings;
  2430. ULONG ulMaxFwdNumRings;
  2431. ULONG ulMaxCallCompletions;
  2432. ULONG ulCallCompletionConds;
  2433. ULONG ulCallCompletionModes;
  2434. ULONG ulNumCompletionMessages;
  2435. ULONG ulCompletionMsgTextEntrySize;
  2436. ULONG ulCompletionMsgTextSize;
  2437. ULONG ulCompletionMsgTextOffset;
  2438. } LINE_ADDRESS_CAPS, *PLINE_ADDRESS_CAPS;
  2439. Return Values:
  2440. NDIS_STATUS_SUCCESS
  2441. NDIS_STATUS_TAPI_INVALADDRESSID
  2442. NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION
  2443. NDIS_STATUS_TAPI_NODRIVER
  2444. ---------------------------------------------------------------------------*/
  2445. {
  2446. HDRV_LINE hdLine = INVALID_LINE_HANDLE;
  2447. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  2448. TRACE( TL_N, TM_Tp, ("+TpGetAddressCaps") );
  2449. if ( pRequest == NULL || pAdapter == NULL )
  2450. {
  2451. TRACE( TL_A, TM_Tp, ("TpGetAddressCaps: Invalid parameter") );
  2452. TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  2453. return NDIS_STATUS_TAPI_INVALPARAM;
  2454. }
  2455. //
  2456. // Retrieve the handle to line context
  2457. //
  2458. hdLine = TpGetHdLineFromDeviceId( pAdapter, pRequest->ulDeviceID );
  2459. if ( hdLine == INVALID_LINE_HANDLE )
  2460. {
  2461. TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_NODRIVER) );
  2462. return NDIS_STATUS_TAPI_NODRIVER;
  2463. }
  2464. //
  2465. // Verify the address id
  2466. //
  2467. if ( pRequest->ulAddressID != 0 )
  2468. {
  2469. TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_INVALADDRESSID) );
  2470. return NDIS_STATUS_TAPI_INVALADDRESSID;
  2471. }
  2472. //
  2473. // Verify the extension versions
  2474. //
  2475. if ( pRequest->ulExtVersion != 0 &&
  2476. pRequest->ulExtVersion != TAPI_EXT_VERSION)
  2477. {
  2478. TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION) );
  2479. return NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION;
  2480. }
  2481. pRequest->LineAddressCaps.ulNeededSize = sizeof( LINE_ADDRESS_CAPS ) +
  2482. sizeof( TAPI_LINE_ADDR_STRING );
  2483. if ( pRequest->LineAddressCaps.ulTotalSize < pRequest->LineAddressCaps.ulNeededSize )
  2484. {
  2485. TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_INVALID_LENGTH) );
  2486. return NDIS_STATUS_INVALID_LENGTH;
  2487. }
  2488. pRequest->LineAddressCaps.ulUsedSize = pRequest->LineAddressCaps.ulNeededSize;
  2489. pRequest->LineAddressCaps.ulDialToneModes = LINEDIALTONEMODE_NORMAL;
  2490. pRequest->LineAddressCaps.ulSpecialInfo = LINESPECIALINFO_UNAVAIL;
  2491. pRequest->LineAddressCaps.ulDisconnectModes = LINEDISCONNECTMODE_NORMAL |
  2492. LINEDISCONNECTMODE_UNKNOWN |
  2493. LINEDISCONNECTMODE_BUSY |
  2494. LINEDISCONNECTMODE_NOANSWER |
  2495. LINEDISCONNECTMODE_UNREACHABLE |
  2496. LINEDISCONNECTMODE_BADADDRESS |
  2497. LINEDISCONNECTMODE_INCOMPATIBLE |
  2498. LINEDISCONNECTMODE_REJECT |
  2499. LINEDISCONNECTMODE_NODIALTONE;
  2500. pRequest->LineAddressCaps.ulMaxNumActiveCalls = pAdapter->nCallsPerLine;
  2501. pRequest->LineAddressCaps.ulMaxNumTransConf = 1;
  2502. pRequest->LineAddressCaps.ulAddrCapFlags = LINEADDRCAPFLAGS_DIALED;
  2503. pRequest->LineAddressCaps.ulCallFeatures = LINECALLFEATURE_ACCEPT |
  2504. LINECALLFEATURE_ANSWER |
  2505. LINECALLFEATURE_COMPLETECALL |
  2506. LINECALLFEATURE_DIAL |
  2507. LINECALLFEATURE_DROP;
  2508. pRequest->LineAddressCaps.ulLineDeviceID = pRequest->ulDeviceID;
  2509. pRequest->LineAddressCaps.ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
  2510. pRequest->LineAddressCaps.ulAddressStates = 0;
  2511. //
  2512. // List of all possible call states.
  2513. //
  2514. pRequest->LineAddressCaps.ulCallStates = TAPI_LINECALLSTATES_SUPPORTED;
  2515. pRequest->LineAddressCaps.ulAddressSize = sizeof( TAPI_LINE_ADDR_STRING );
  2516. pRequest->LineAddressCaps.ulAddressOffset = sizeof( LINE_ADDRESS_CAPS );
  2517. {
  2518. CHAR* pBuf;
  2519. pBuf = ( (PUCHAR) &pRequest->LineAddressCaps ) + sizeof( LINE_ADDRESS_CAPS );
  2520. NdisMoveMemory( pBuf, TAPI_LINE_ADDR_STRING, sizeof( TAPI_LINE_ADDR_STRING ) );
  2521. }
  2522. TRACE( TL_N, TM_Tp, ("-TpGetAddressCaps=$%x",NDIS_STATUS_SUCCESS) );
  2523. return NDIS_STATUS_SUCCESS;
  2524. }
  2525. NDIS_STATUS
  2526. TpSetStatusMessages(
  2527. IN ADAPTER* pAdapter,
  2528. IN PNDIS_TAPI_SET_STATUS_MESSAGES pRequest
  2529. )
  2530. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2531. Functional Description:
  2532. This request enables the Connection Wrapper to specify which notification
  2533. messages the miniport should generate for events related to status changes
  2534. for the specified line or any of its addresses. By default, address and
  2535. line status reporting is initially disabled for a line.
  2536. Parameters:
  2537. pAdapter _ A pointer to our adapter information structure.
  2538. pRequest _ A pointer to the NDIS_TAPI request structure for this call.
  2539. typedef struct _NDIS_TAPI_SET_STATUS_MESSAGES
  2540. {
  2541. IN ULONG ulRequestID;
  2542. IN HDRV_LINE hdLine;
  2543. IN ULONG ulLineStates;
  2544. IN ULONG ulAddressStates;
  2545. } NDIS_TAPI_SET_STATUS_MESSAGES, *PNDIS_TAPI_SET_STATUS_MESSAGES;
  2546. Return Values:
  2547. NDIS_STATUS_SUCCESS
  2548. NDIS_STATUS_TAPI_INVALLINEHANDLE
  2549. NDIS_STATUS_TAPI_INVALLINESTATE
  2550. NDIS_STATUS_TAPI_INVALADDRESSSTATE
  2551. ---------------------------------------------------------------------------*/
  2552. {
  2553. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  2554. TRACE( TL_N, TM_Tp, ("+TpSetStatusMessages") );
  2555. //
  2556. // We do not send any line or address state change notifications at all,
  2557. // so we do not care about it.
  2558. //
  2559. // We care about call notification messages and they are always on by default.
  2560. //
  2561. TRACE( TL_N, TM_Tp, ("-TpSetStatusMessages=$%x",NDIS_STATUS_SUCCESS) );
  2562. return NDIS_STATUS_SUCCESS;
  2563. }
  2564. VOID
  2565. TpCallStateChangeHandler(
  2566. IN CALL* pCall,
  2567. IN ULONG ulCallState,
  2568. IN ULONG ulStateParam
  2569. )
  2570. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2571. Functional Description:
  2572. This routine will indicate the given LINECALLSTATE to the Connection
  2573. wrapper if the event has been enabled by the wrapper. Otherwise the state
  2574. information is saved, but no indication is made.
  2575. LINECALLSTATE_ Constants: The LINECALLSTATE_ bit-flag constants describe the
  2576. call states a call can be in.
  2577. LINECALLSTATE_ACCEPTED:
  2578. The call was in the offering state and has been accepted. This indicates to
  2579. other (monitoring) applications that the current owner application has
  2580. claimed responsibility for answering the call. In ISDN, the accepted state is
  2581. entered when the called-party equipment sends a message to the switch
  2582. indicating that it is willing to present the call to the called person. This
  2583. has the side effect of alerting (ringing) the users at both ends of the call.
  2584. An incoming call can always be immediately answered without first being
  2585. separately accepted.
  2586. LINECALLSTATE_BUSY
  2587. The call is receiving a busy tone. A busy tone indicates that the call cannot
  2588. be completed either a circuit (trunk) or the remote party's station are in use
  2589. . See LINEBUSYMODE_ Constants.
  2590. LINECALLSTATE_CONFERENCED
  2591. The call is a member of a conference call and is logically in the connected
  2592. state.
  2593. LINECALLSTATE_CONNECTED
  2594. The call has been established and the connection is made. Information is able
  2595. to flow over the call between the originating address and the destination
  2596. address.
  2597. LINECALLSTATE_DIALING
  2598. The originator is dialing digits on the call. The dialed digits are collected
  2599. by the switch. Note that neither lineGenerateDigits nor
  2600. TSPI_lineGenerateDigits will place the line into the dialing state.
  2601. LINECALLSTATE_DIALTONE
  2602. The call is receiving a dial tone from the switch, which means that the
  2603. switch is ready to receive a dialed number. See LINEDIALTONEMODE_ Constants
  2604. for identifiers of special dial tones, such as a stutter tone of normal voice
  2605. mail.
  2606. LINECALLSTATE_DISCONNECTED
  2607. The remote party has disconnected from the call.
  2608. LINECALLSTATE_IDLE
  2609. The call exists but has not been connected. No activity exists on the call,
  2610. which means that no call is currently active. A call can never transition
  2611. into the idle state.
  2612. LINECALLSTATE_OFFERING
  2613. The call is being offered to the station, signaling the arrival of a new call
  2614. . The offering state is not the same as causing a phone or computer to ring.
  2615. In some environments, a call in the offering state does not ring the user
  2616. until the switch instructs the line to ring. An example use might be where an
  2617. incoming call appears on several station sets but only the primary address
  2618. rings. The instruction to ring does not affect any call states.
  2619. LINECALLSTATE_ONHOLD
  2620. The call is on hold by the switch. This frees the physical line, which allows
  2621. another call to use the line.
  2622. LINECALLSTATE_ONHOLDPENDCONF
  2623. The call is currently on hold while it is being added to a conference.
  2624. LINECALLSTATE_ONHOLDPENDTRANSFER
  2625. The call is currently on hold awaiting transfer to another number.
  2626. LINECALLSTATE_PROCEEDING
  2627. Dialing has completed and the call is proceeding through the switch or
  2628. telephone network. This occurs after dialing is complete and before the call
  2629. reaches the dialed party, as indicated by ringback, busy, or answer.
  2630. LINECALLSTATE_RINGBACK
  2631. The station to be called has been reached, and the destination's switch is
  2632. generating a ring tone back to the originator. A ringback means that the
  2633. destination address is being alerted to the call.
  2634. LINECALLSTATE_SPECIALINFO
  2635. The call is receiving a special information signal, which precedes a
  2636. prerecorded announcement indicating why a call cannot be completed. See
  2637. LINESPECIALINFO_ Constants.
  2638. LINECALLSTATE_UNKNOWN
  2639. The call exists, but its state is currently unknown. This may be the result
  2640. of poor call progress detection by the service provider. A call state message
  2641. with the call state set to unknown may also be generated to inform the TAPI
  2642. DLL about a new call at a time when the actual call state of the call is not
  2643. exactly known.
  2644. Parameters:
  2645. pCall _ A pointer to our call information structure.
  2646. ulCallState _ The LINECALLSTATE event to be posted to TAPI/WAN.
  2647. ulStateParam _ This value depends on the event being posted, and some
  2648. events will pass in zero if they don't use this parameter.
  2649. Return Values:
  2650. None
  2651. ---------------------------------------------------------------------------*/
  2652. {
  2653. BOOLEAN fIndicateStatus = FALSE;
  2654. NDIS_TAPI_EVENT TapiEvent;
  2655. ULONG ulOldCallState;
  2656. ASSERT( VALIDATE_CALL( pCall ) );
  2657. TRACE( TL_N, TM_Tp, ("+TpCallStateChangeHandler") );
  2658. NdisAcquireSpinLock( &pCall->lockCall );
  2659. do
  2660. {
  2661. //
  2662. // Check if we have a valid htCall member, otherwise it means we are already done,
  2663. // so we should not give any more notifications to TAPI about state changes
  2664. //
  2665. if ( pCall->htCall == (HTAPI_CALL) NULL )
  2666. {
  2667. TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: No valid htCall") );
  2668. break;
  2669. }
  2670. //
  2671. // A connect notification can come only after a PROCEEDING or OFFERING state
  2672. // is reached
  2673. //
  2674. if ( ulCallState == LINECALLSTATE_CONNECTED &&
  2675. ( pCall->ulTapiCallState != LINECALLSTATE_OFFERING &&
  2676. pCall->ulTapiCallState != LINECALLSTATE_PROCEEDING ) )
  2677. {
  2678. TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: Invalid order of state change") );
  2679. break;
  2680. }
  2681. //
  2682. // If the new state is the same as old state, just return
  2683. //
  2684. if ( pCall->ulTapiCallState == ulCallState )
  2685. {
  2686. TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: No state change") );
  2687. break;
  2688. }
  2689. //
  2690. // Otherwise, change the calls state, and
  2691. // make a notification to TAPI about the new state
  2692. //
  2693. ulOldCallState = pCall->ulTapiCallState;
  2694. pCall->ulTapiCallState = ulCallState;
  2695. TapiEvent.htLine = pCall->pLine->htLine;
  2696. TapiEvent.htCall = pCall->htCall;
  2697. TapiEvent.ulMsg = LINE_CALLSTATE;
  2698. TapiEvent.ulParam1 = ulCallState;
  2699. TapiEvent.ulParam2 = ulStateParam;
  2700. TapiEvent.ulParam3 = LINEMEDIAMODE_DIGITALDATA;
  2701. fIndicateStatus = TRUE;
  2702. if ( ulCallState == LINECALLSTATE_CONNECTED )
  2703. {
  2704. ADAPTER* pAdapter = pCall->pLine->pAdapter;
  2705. //
  2706. // Since the call is connected, reset CLBF_CallConnectPending bit
  2707. //
  2708. pCall->ulClFlags &= ~CLBF_CallConnectPending;
  2709. //
  2710. // Also prepare the WanLinkInfo structure of call context now
  2711. // as right after we indicate line-up to NDISWAN, it will query us
  2712. // for this info.
  2713. //
  2714. NdisZeroMemory( &pCall->NdisWanLinkInfo, sizeof( pCall->NdisWanLinkInfo ) );
  2715. pCall->NdisWanLinkInfo.MaxSendFrameSize = pCall->ulMaxFrameSize;
  2716. pCall->NdisWanLinkInfo.MaxRecvFrameSize = pCall->ulMaxFrameSize;
  2717. pCall->NdisWanLinkInfo.HeaderPadding = pAdapter->NdisWanInfo.HeaderPadding;
  2718. pCall->NdisWanLinkInfo.TailPadding = pAdapter->NdisWanInfo.TailPadding;
  2719. pCall->NdisWanLinkInfo.SendFramingBits = pAdapter->NdisWanInfo.FramingBits;
  2720. pCall->NdisWanLinkInfo.RecvFramingBits = pAdapter->NdisWanInfo.FramingBits;
  2721. pCall->NdisWanLinkInfo.SendACCM = 0;
  2722. pCall->NdisWanLinkInfo.RecvACCM = 0;
  2723. }
  2724. else if ( ulCallState == LINECALLSTATE_DISCONNECTED )
  2725. {
  2726. TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: LINEDISCONNECTMODE: %x", ulStateParam ) );
  2727. //
  2728. // This state change will only occur if TpDropCall() is in progress,
  2729. // so we invalidate the htCall member of call context in order to prevent
  2730. // a possible out of sync state change notification.
  2731. //
  2732. pCall->htCall = (HTAPI_CALL) NULL;
  2733. }
  2734. } while ( FALSE) ;
  2735. NdisReleaseSpinLock( &pCall->lockCall );
  2736. //
  2737. // Notify state change to TAPI if needed
  2738. //
  2739. if ( fIndicateStatus )
  2740. {
  2741. TRACE( TL_N, TM_Tp, ("TpCallStateChangeHandler: Indicate LINE_CALLSTATE change: %x -> %x",ulOldCallState,ulCallState ) );
  2742. NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
  2743. NDIS_STATUS_TAPI_INDICATION,
  2744. &TapiEvent,
  2745. sizeof( NDIS_TAPI_EVENT ) );
  2746. }
  2747. TRACE( TL_N, TM_Tp, ("-TpCallStateChangeHandler") );
  2748. }
  2749. NDIS_STATUS
  2750. TpMakeCall(
  2751. IN ADAPTER* pAdapter,
  2752. IN PNDIS_TAPI_MAKE_CALL pRequest,
  2753. IN ULONG ulRequestLength
  2754. )
  2755. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2756. Functional Description:
  2757. This request places a call on the specified line to the specified
  2758. destination address. Optionally, call parameters can be specified if
  2759. anything but default call setup parameters are requested.
  2760. Parameters:
  2761. Adapter _ A pointer ot our adapter information structure.
  2762. Request _ A pointer to the NDIS_TAPI request structure for this call.
  2763. typedef struct _NDIS_TAPI_MAKE_CALL
  2764. {
  2765. IN ULONG ulRequestID;
  2766. IN HDRV_LINE hdLine;
  2767. IN HTAPI_CALL htCall;
  2768. OUT HDRV_CALL hdCall;
  2769. IN ULONG ulDestAddressSize;
  2770. IN ULONG ulDestAddressOffset;
  2771. IN BOOLEAN bUseDefaultLineCallParams;
  2772. IN LINE_CALL_PARAMS LineCallParams;
  2773. } NDIS_TAPI_MAKE_CALL, *PNDIS_TAPI_MAKE_CALL;
  2774. typedef struct _LINE_CALL_PARAMS // Defaults:
  2775. {
  2776. ULONG ulTotalSize; // ---------
  2777. ULONG ulBearerMode; // voice
  2778. ULONG ulMinRate; // (3.1kHz)
  2779. ULONG ulMaxRate; // (3.1kHz)
  2780. ULONG ulMediaMode; // interactiveVoice
  2781. ULONG ulCallParamFlags; // 0
  2782. ULONG ulAddressMode; // addressID
  2783. ULONG ulAddressID; // (any available)
  2784. LINE_DIAL_PARAMS DialParams; // (0, 0, 0, 0)
  2785. ULONG ulOrigAddressSize; // 0
  2786. ULONG ulOrigAddressOffset;
  2787. ULONG ulDisplayableAddressSize;
  2788. ULONG ulDisplayableAddressOffset;
  2789. ULONG ulCalledPartySize; // 0
  2790. ULONG ulCalledPartyOffset;
  2791. ULONG ulCommentSize; // 0
  2792. ULONG ulCommentOffset;
  2793. ULONG ulUserUserInfoSize; // 0
  2794. ULONG ulUserUserInfoOffset;
  2795. ULONG ulHighLevelCompSize; // 0
  2796. ULONG ulHighLevelCompOffset;
  2797. ULONG ulLowLevelCompSize; // 0
  2798. ULONG ulLowLevelCompOffset;
  2799. ULONG ulDevSpecificSize; // 0
  2800. ULONG ulDevSpecificOffset;
  2801. } LINE_CALL_PARAMS, *PLINE_CALL_PARAMS;
  2802. typedef struct _LINE_DIAL_PARAMS
  2803. {
  2804. ULONG ulDialPause;
  2805. ULONG ulDialSpeed;
  2806. ULONG ulDigitDuration;
  2807. ULONG ulWaitForDialtone;
  2808. } LINE_DIAL_PARAMS, *PLINE_DIAL_PARAMS;
  2809. RequestLength _ Length of the request buffer
  2810. Return Values:
  2811. NDIS_STATUS_TAPI_ADDRESSBLOCKED
  2812. NDIS_STATUS_TAPI_BEARERMODEUNAVAIL
  2813. NDIS_STATUS_TAPI_CALLUNAVAIL
  2814. NDIS_STATUS_TAPI_DIALBILLING
  2815. NDIS_STATUS_TAPI_DIALQUIET
  2816. NDIS_STATUS_TAPI_DIALDIALTONE
  2817. NDIS_STATUS_TAPI_DIALPROMPT
  2818. NDIS_STATUS_TAPI_INUSE
  2819. NDIS_STATUS_TAPI_INVALADDRESSMODE
  2820. NDIS_STATUS_TAPI_INVALBEARERMODE
  2821. NDIS_STATUS_TAPI_INVALMEDIAMODE
  2822. NDIS_STATUS_TAPI_INVALLINESTATE
  2823. NDIS_STATUS_TAPI_INVALRATE
  2824. NDIS_STATUS_TAPI_INVALLINEHANDLE
  2825. NDIS_STATUS_TAPI_INVALADDRESS
  2826. NDIS_STATUS_TAPI_INVALADDRESSID
  2827. NDIS_STATUS_TAPI_INVALCALLPARAMS
  2828. NDIS_STATUS_RESOURCES
  2829. NDIS_STATUS_TAPI_OPERATIONUNAVAIL
  2830. NDIS_STATUS_FAILURE
  2831. NDIS_STATUS_TAPI_RESOURCEUNAVAIL
  2832. NDIS_STATUS_TAPI_RATEUNAVAIL
  2833. NDIS_STATUS_TAPI_USERUSERINFOTOOBIG
  2834. ---------------------------------------------------------------------------*/
  2835. {
  2836. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  2837. LINE* pLine = NULL;
  2838. CALL* pCall = NULL;
  2839. HDRV_CALL hdCall = (HDRV_CALL) NULL;
  2840. BOOLEAN fCallInsertedToHandleTable = FALSE;
  2841. WORKITEM* pWorkItem = NULL;
  2842. PVOID Args[4];
  2843. BOOLEAN fRenumerationNotScheduled = FALSE;
  2844. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  2845. TRACE( TL_N, TM_Tp, ("+TpMakeCall") );
  2846. if ( pRequest == NULL || pAdapter == NULL )
  2847. {
  2848. TRACE( TL_A, TM_Tp, ("TpMakeCall: Invalid parameter") );
  2849. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  2850. return NDIS_STATUS_TAPI_INVALPARAM;
  2851. }
  2852. //
  2853. // Retrieve a pointer to the line context
  2854. //
  2855. pLine = TpGetLinePtrFromHdLine( pAdapter, pRequest->hdLine );
  2856. if ( pLine == NULL )
  2857. {
  2858. status = NDIS_STATUS_TAPI_INVALLINEHANDLE;
  2859. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2860. return status;
  2861. }
  2862. //
  2863. // See if we can make calls on this line at all
  2864. //
  2865. if ( ! (pLine->ulLnFlags & LNBF_MakeOutgoingCalls ) )
  2866. {
  2867. status = NDIS_STATUS_TAPI_ADDRESSBLOCKED;
  2868. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2869. return status;
  2870. }
  2871. //
  2872. // See if we can still make calls on this line
  2873. //
  2874. if ( pLine->nActiveCalls == pLine->nMaxCalls )
  2875. {
  2876. status = NDIS_STATUS_TAPI_OPERATIONUNAVAIL;
  2877. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2878. return status;
  2879. }
  2880. //
  2881. // Make sure the parameters suppied in the request are acceptable
  2882. //
  2883. if ( pRequest->bUseDefaultLineCallParams )
  2884. {
  2885. status = NDIS_STATUS_TAPI_INVALCALLPARAMS;
  2886. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2887. return status;
  2888. }
  2889. if ( !( pRequest->LineCallParams.ulBearerMode & LINEBEARERMODE_DATA ) )
  2890. {
  2891. status = NDIS_STATUS_TAPI_INVALBEARERMODE;
  2892. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2893. return status;
  2894. }
  2895. if ( !( pRequest->LineCallParams.ulMediaMode & LINEMEDIAMODE_DIGITALDATA ) )
  2896. {
  2897. status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
  2898. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2899. return status;
  2900. }
  2901. if ( !( pRequest->LineCallParams.ulAddressMode &
  2902. ( LINEADDRESSMODE_ADDRESSID | LINEADDRESSMODE_DIALABLEADDR ) ) )
  2903. {
  2904. status = NDIS_STATUS_TAPI_INVALADDRESSMODE;
  2905. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2906. return status;
  2907. }
  2908. if ( pRequest->LineCallParams.ulAddressID > 0 )
  2909. {
  2910. status = NDIS_STATUS_TAPI_INVALADDRESSID;
  2911. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2912. return status;
  2913. }
  2914. if ( pRequest->ulDestAddressOffset + pRequest->ulDestAddressSize > ulRequestLength )
  2915. {
  2916. status = NDIS_STATUS_TAPI_INVALPARAM;
  2917. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2918. return status;
  2919. }
  2920. //
  2921. // Create a call context
  2922. //
  2923. if ( ALLOC_CALL( &pCall ) != NDIS_STATUS_SUCCESS )
  2924. {
  2925. status = NDIS_STATUS_RESOURCES;
  2926. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  2927. return status;
  2928. }
  2929. do
  2930. {
  2931. //
  2932. // Initialize the call context
  2933. //
  2934. status = TpCallInitialize( pCall, pLine, pRequest->htCall, FALSE /* fIncoming */ );
  2935. if ( status != NDIS_STATUS_SUCCESS )
  2936. break;
  2937. //
  2938. // Insert the call context into the tapi provider's handle table
  2939. //
  2940. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2941. hdCall = (HDRV_CALL) InsertToHandleTable( pAdapter->TapiProv.hCallTable,
  2942. NO_PREFERED_INDEX,
  2943. pCall );
  2944. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2945. if ( hdCall == (HDRV_CALL) NULL )
  2946. {
  2947. status = NDIS_STATUS_TAPI_CALLUNAVAIL;
  2948. break;
  2949. }
  2950. fCallInsertedToHandleTable = TRUE;
  2951. //
  2952. // Set the call's hdCall member
  2953. //
  2954. pCall->hdCall = hdCall;
  2955. //
  2956. // Set AC Name and the service name passed in the request.
  2957. // We expect it in the following format:
  2958. // AC Name\Service Name
  2959. //
  2960. // The following examles are all valid:
  2961. // AC Name\ -> Connect to the default service on the specified AC
  2962. // Service Name -> Connect to the specified service on any AC
  2963. // AC Name\Service Name -> Connect to the specified service on the specified AC
  2964. // -> Connect to the default service on any AC
  2965. //
  2966. // We will also strip off any leading or trailing space chars.
  2967. //
  2968. {
  2969. CHAR* pBuf = ( (PUCHAR) pRequest ) + pRequest->ulDestAddressOffset;
  2970. ULONG size = pRequest->ulDestAddressSize;
  2971. ULONG ACNameStartPos, ACNameEndPos;
  2972. ULONG ServiceNameStartPos, ServiceNameEndPos;
  2973. //
  2974. // Remove the terminating NULL characters if passed any.
  2975. //
  2976. for ( ; size > 0 ; size-- )
  2977. {
  2978. if ( pBuf[ size - 1] != '\0' )
  2979. {
  2980. break;
  2981. }
  2982. }
  2983. //
  2984. // Get the AC Name and service name
  2985. //
  2986. do
  2987. {
  2988. ULONG i = 0;
  2989. CHAR* pTempChar = pBuf;
  2990. ACNameStartPos = ACNameEndPos = 0;
  2991. ServiceNameStartPos = ServiceNameEndPos = 0;
  2992. //
  2993. // Skip leading spaces
  2994. //
  2995. while (i < size)
  2996. {
  2997. if (*pTempChar != ' ')
  2998. {
  2999. break;
  3000. }
  3001. i++;
  3002. pTempChar++;
  3003. }
  3004. if (i == size)
  3005. {
  3006. break;
  3007. }
  3008. ACNameStartPos = ACNameEndPos = i;
  3009. while (i < size)
  3010. {
  3011. if (*pTempChar == '\\')
  3012. {
  3013. break;
  3014. }
  3015. i++;
  3016. if (*pTempChar != ' ')
  3017. {
  3018. //
  3019. // Mark the beginning of trailing spaces
  3020. //
  3021. ACNameEndPos = i;
  3022. }
  3023. pTempChar++;
  3024. }
  3025. if (i == size)
  3026. {
  3027. //
  3028. // No AC Name was specified, it was just Service Name
  3029. // and we parsed it
  3030. //
  3031. ServiceNameStartPos = ACNameStartPos;
  3032. ServiceNameEndPos = ACNameEndPos;
  3033. ACNameStartPos = ACNameEndPos = 0;
  3034. break;
  3035. }
  3036. //
  3037. // Advance 'i' and 'pTempChar' once to skip the '\' character
  3038. //
  3039. i++;
  3040. pTempChar++;
  3041. //
  3042. // Skip leading spaces
  3043. //
  3044. while (i < size)
  3045. {
  3046. if (*pTempChar != ' ')
  3047. {
  3048. break;
  3049. }
  3050. i++;
  3051. pTempChar++;
  3052. }
  3053. if (i == size)
  3054. {
  3055. break;
  3056. }
  3057. ServiceNameStartPos = ServiceNameEndPos = i;
  3058. while (i < size)
  3059. {
  3060. i++;
  3061. if (*pTempChar != ' ')
  3062. {
  3063. //
  3064. // Mark the beginning of trailing spaces
  3065. //
  3066. ServiceNameEndPos = i;
  3067. }
  3068. pTempChar++;
  3069. }
  3070. } while ( FALSE );
  3071. //
  3072. // Retrieve the AC Name information into the call context
  3073. //
  3074. pCall->nACNameLength = (USHORT) ( ( MAX_AC_NAME_LENGTH < ( ACNameEndPos - ACNameStartPos ) ) ?
  3075. MAX_AC_NAME_LENGTH : ( ACNameEndPos - ACNameStartPos ) );
  3076. if ( pCall->nACNameLength != 0 )
  3077. {
  3078. NdisMoveMemory( pCall->ACName, &pBuf[ACNameStartPos], pCall->nACNameLength );
  3079. pCall->fACNameSpecified = TRUE;
  3080. }
  3081. //
  3082. // Retrieve the Service Name information into the call context
  3083. //
  3084. pCall->nServiceNameLength = (USHORT) ( ( MAX_SERVICE_NAME_LENGTH < ( ServiceNameEndPos - ServiceNameStartPos ) ) ?
  3085. MAX_SERVICE_NAME_LENGTH : ( ServiceNameEndPos - ServiceNameStartPos ) );
  3086. if ( pCall->nServiceNameLength != 0 )
  3087. {
  3088. NdisMoveMemory( pCall->ServiceName, &pBuf[ServiceNameStartPos], pCall->nServiceNameLength );
  3089. }
  3090. }
  3091. //
  3092. // Allocate a work item for scheduling FsmMakeCall()
  3093. //
  3094. // Set the arguements array
  3095. //
  3096. Args[0] = (PVOID) pCall;
  3097. pWorkItem = AllocWorkItem( &gl_llistWorkItems,
  3098. ExecAdapterWorkItem,
  3099. NULL,
  3100. Args,
  3101. CWT_workFsmMakeCall );
  3102. if ( pWorkItem == NULL )
  3103. {
  3104. status = NDIS_STATUS_RESOURCES;
  3105. break;
  3106. }
  3107. {
  3108. //
  3109. // Schedule a work item to reenumerate bindings
  3110. //
  3111. WORKITEM* pCallWorkItem;
  3112. Args[0] = (PVOID) BN_SetFiltersForMakeCall; // Is a set filter request
  3113. Args[1] = (PVOID) pCall;
  3114. Args[2] = (PVOID) pRequest;
  3115. Args[3] = (PVOID) pWorkItem;
  3116. pCallWorkItem = pWorkItem;
  3117. //
  3118. // Allocate work item for the bind
  3119. //
  3120. pWorkItem = AllocWorkItem( &gl_llistWorkItems,
  3121. ExecBindingWorkItem,
  3122. NULL,
  3123. Args,
  3124. BWT_workPrStartBinds );
  3125. if ( pWorkItem == NULL )
  3126. {
  3127. //
  3128. // We can not allocate the work item for reenumeration of bindings
  3129. // But may be all enumerations are intact, so let the
  3130. // make call request continue
  3131. //
  3132. pWorkItem = pCallWorkItem;
  3133. fRenumerationNotScheduled = TRUE;
  3134. }
  3135. }
  3136. //
  3137. // Insert the call context into the line's active call list
  3138. //
  3139. NdisAcquireSpinLock( &pLine->lockLine );
  3140. InsertHeadList( &pLine->linkCalls, &pCall->linkCalls );
  3141. pLine->nActiveCalls++;
  3142. ReferenceLine( pLine, FALSE );
  3143. NdisReleaseSpinLock( &pLine->lockLine );
  3144. //
  3145. // Reference the call 3 times:
  3146. // 1. For scheduling of FsmMakeCall()
  3147. // 2. For dropping of the call
  3148. // 3. For closing of the call
  3149. //
  3150. NdisAcquireSpinLock( &pCall->lockCall );
  3151. ReferenceCall( pCall, FALSE );
  3152. ReferenceCall( pCall, FALSE );
  3153. ReferenceCall( pCall, FALSE );
  3154. NdisReleaseSpinLock( &pCall->lockCall );
  3155. //
  3156. // Schedule the bind operation
  3157. //
  3158. ScheduleWorkItem( pWorkItem );
  3159. status = NDIS_STATUS_SUCCESS;
  3160. } while ( FALSE );
  3161. if ( status == NDIS_STATUS_SUCCESS )
  3162. {
  3163. //
  3164. // If succesfull, return the call handle to TAPI and mark call as TAPI notified
  3165. // of new call
  3166. //
  3167. pRequest->hdCall = hdCall;
  3168. //
  3169. // If we have scheduled a reenumeration work item, then pend this request
  3170. // It will be completed when reenumeration is complete.
  3171. //
  3172. if ( !fRenumerationNotScheduled )
  3173. {
  3174. status = NDIS_STATUS_PENDING;
  3175. }
  3176. }
  3177. else
  3178. {
  3179. //
  3180. // Somethings failed, do clean up
  3181. //
  3182. if ( fCallInsertedToHandleTable )
  3183. {
  3184. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  3185. RemoveFromHandleTable( pAdapter->TapiProv.hCallTable, (NDIS_HANDLE) hdCall );
  3186. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  3187. }
  3188. if ( pCall )
  3189. {
  3190. TpCallCleanup( pCall );
  3191. }
  3192. }
  3193. TRACE( TL_N, TM_Tp, ("-TpMakeCall=$%x",status) );
  3194. return status;
  3195. }
  3196. VOID
  3197. TpMakeCallComplete(
  3198. IN CALL* pCall,
  3199. IN PNDIS_TAPI_MAKE_CALL pRequest
  3200. )
  3201. {
  3202. TRACE( TL_N, TM_Tp, ("+TpMakeCallComplete") );
  3203. NdisMQueryInformationComplete( pCall->pLine->pAdapter->MiniportAdapterHandle,
  3204. NDIS_STATUS_SUCCESS );
  3205. TRACE( TL_N, TM_Tp, ("-TpMakeCallComplete=$%x",NDIS_STATUS_SUCCESS) );
  3206. }
  3207. NDIS_STATUS
  3208. TpCallInitialize(
  3209. IN CALL* pCall,
  3210. IN LINE* pLine,
  3211. IN HTAPI_CALL htCall,
  3212. IN BOOLEAN fIncoming
  3213. )
  3214. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3215. Functional Description:
  3216. This function makes initialization on the call context.
  3217. Parameters:
  3218. pCall _ A pointer to our call information structure.
  3219. pLine _ A pointer to the line information structure that the call belongs.
  3220. htCall _ Handle assigned to the call by TAPI.
  3221. fIncoming _ Flag that indicates if the call is inbound or outbound.
  3222. Return Values:
  3223. NDIS_STATUS_SUCCESS
  3224. NDIS_STATUS_FAILURE
  3225. ---------------------------------------------------------------------------*/
  3226. {
  3227. TRACE( TL_N, TM_Tp, ("+TpCallInitialize") );
  3228. NdisZeroMemory( pCall, sizeof( CALL ) );
  3229. InitializeListHead( &pCall->linkCalls );
  3230. pCall->tagCall = MTAG_CALL;
  3231. pCall->ulClFlags = ( CLBF_CallOpen | CLBF_CallConnectPending );
  3232. NdisAllocateSpinLock( &pCall->lockCall );
  3233. pCall->fIncoming = fIncoming;
  3234. pCall->pLine = pLine;
  3235. pCall->htCall = htCall;
  3236. InitializeListHead( &pCall->linkReceivedPackets );
  3237. pCall->ulTapiCallState = LINECALLSTATE_IDLE;
  3238. TRACE( TL_N, TM_Tp, ("-TpCallInitialize") );
  3239. return NDIS_STATUS_SUCCESS;
  3240. }
  3241. NDIS_STATUS
  3242. TpAnswerCall(
  3243. IN ADAPTER* pAdapter,
  3244. IN PNDIS_TAPI_ANSWER pRequest
  3245. )
  3246. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3247. Functional Description:
  3248. This request answers the specified offering call. It may optionally send
  3249. the specified user-to-user information to the calling party.
  3250. Parameters:
  3251. Adapter _ A pointer ot our adapter information structure.
  3252. Request _ A pointer to the NDIS_TAPI request structure for this call.
  3253. typedef struct _NDIS_TAPI_ANSWER
  3254. {
  3255. IN ULONG ulRequestID;
  3256. IN HDRV_CALL hdCall;
  3257. IN ULONG ulUserUserInfoSize;
  3258. IN UCHAR UserUserInfo[1];
  3259. } NDIS_TAPI_ANSWER, *PNDIS_TAPI_ANSWER;
  3260. Return Values:
  3261. NDIS_STATUS_SUCCESS
  3262. NDIS_STATUS_TAPI_INVALCALLHANDLE
  3263. ---------------------------------------------------------------------------*/
  3264. {
  3265. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  3266. CALL* pCall = NULL;
  3267. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  3268. TRACE( TL_N, TM_Tp, ("+TpAnswerCall") );
  3269. if ( pRequest == NULL || pAdapter == NULL )
  3270. {
  3271. TRACE( TL_A, TM_Tp, ("TpAnswerCall: Invalid parameter") );
  3272. TRACE( TL_N, TM_Tp, ("-TpAnswerCall=$%x",NDIS_STATUS_TAPI_INVALPARAM) );
  3273. return NDIS_STATUS_TAPI_INVALPARAM;
  3274. }
  3275. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  3276. (NDIS_HANDLE) pRequest->hdCall );
  3277. if ( pCall == NULL )
  3278. {
  3279. status = NDIS_STATUS_TAPI_INVALCALLHANDLE;
  3280. TRACE( TL_N, TM_Tp, ("-TpAnswerCall=$%x",status) );
  3281. return status;
  3282. }
  3283. status = FsmAnswerCall( pCall );
  3284. TRACE( TL_N, TM_Tp, ("-TpAnswerCall=$%x",status) );
  3285. return status;
  3286. }
  3287. VOID
  3288. ExecAdapterWorkItem(
  3289. IN PVOID Args[4],
  3290. IN UINT workType
  3291. )
  3292. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3293. Functional Description:
  3294. This function executes the scheduled work items for the adapter.
  3295. Parameters:
  3296. Args:
  3297. An array of length 4 keeping PVOIDs
  3298. workType:
  3299. Indicates the type of the work to be executed.
  3300. We use this to understand what we should do in this function.
  3301. Return Values:
  3302. None
  3303. ---------------------------------------------------------------------------*/
  3304. {
  3305. TRACE( TL_N, TM_Mp, ("+ExecAdapterWorkItem") );
  3306. switch ( workType )
  3307. {
  3308. case CWT_workFsmMakeCall:
  3309. //
  3310. // Scheduled from TpMakeCall() to start an outgoing call
  3311. //
  3312. {
  3313. CALL* pCall = (CALL*) Args[0];
  3314. FsmMakeCall( pCall );
  3315. //
  3316. // Remove the reference due to scheduling of FsmMakeCall()
  3317. //
  3318. DereferenceCall( pCall );
  3319. break;
  3320. }
  3321. default:
  3322. break;
  3323. }
  3324. TRACE( TL_N, TM_Mp, ("-ExecAdapterWorkItem") );
  3325. }
  3326. VOID
  3327. TpReceiveCall(
  3328. IN ADAPTER* pAdapter,
  3329. IN BINDING* pBinding,
  3330. IN PPPOE_PACKET* pPacket
  3331. )
  3332. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3333. Functional Description:
  3334. This function will be called by miniport when we receive a PADR packet
  3335. to initiate a call.
  3336. Parameters:
  3337. pAdapter:
  3338. A pointer to our adapter information structure.
  3339. pPacket:
  3340. A pointer to the received PADI packet.
  3341. Return Values:
  3342. None
  3343. ---------------------------------------------------------------------------*/
  3344. {
  3345. HANDLE_TABLE hCallTable = NULL;
  3346. UINT hCallTableSize = 0;
  3347. UINT nIndex = 0;
  3348. LINE* pLine = NULL;
  3349. CALL* pCall = NULL;
  3350. UINT i;
  3351. NDIS_STATUS status;
  3352. BOOLEAN fCallInsertedToHandleTable = FALSE;
  3353. TRACE( TL_N, TM_Tp, ("+TpReceiveCall") );
  3354. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  3355. //
  3356. // Traverse the call handle table and find an empty spot
  3357. //
  3358. hCallTableSize = pAdapter->nMaxLines * pAdapter->nCallsPerLine;
  3359. hCallTable = pAdapter->TapiProv.hCallTable;
  3360. for ( nIndex = 0; nIndex < hCallTableSize; nIndex++ )
  3361. {
  3362. if ( RetrieveFromHandleTableByIndex( hCallTable, (USHORT) nIndex ) == NULL )
  3363. break;
  3364. }
  3365. if ( nIndex == hCallTableSize )
  3366. {
  3367. //
  3368. // We are already maxed out with current calls, do not respond to the request
  3369. //
  3370. // TODO: We could send a PADO packet with an error tag saying that we can
  3371. // not accept calls temporarily.
  3372. //
  3373. TRACE( TL_N, TM_Tp, ("-TpReceiveCall: Can not take calls - Call table full") );
  3374. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  3375. return;
  3376. }
  3377. //
  3378. // We have found an empty spot, now see if any of the open lines accept calls
  3379. //
  3380. for ( i = 0; i < pAdapter->nMaxLines; i++ )
  3381. {
  3382. pLine = pAdapter->TapiProv.LineTable[i];
  3383. if ( pLine == NULL )
  3384. continue;
  3385. if ( pLine->nActiveCalls == pAdapter->nCallsPerLine )
  3386. {
  3387. pLine = NULL;
  3388. continue;
  3389. }
  3390. if ( !( pLine->ulLnFlags & LNBF_AcceptIncomingCalls ) )
  3391. {
  3392. pLine = NULL;
  3393. continue;
  3394. }
  3395. break;
  3396. }
  3397. if ( pLine == NULL )
  3398. {
  3399. //
  3400. // We do not have any lines accepting calls right now
  3401. //
  3402. // TODO: We could send a PADO packet with an error tag saying that there are
  3403. // no active lines accepting calls at the moment.
  3404. //
  3405. TRACE( TL_N, TM_Tp, ("-TpReceiveCall: Can not take calls - No lines taking calls") );
  3406. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  3407. return;
  3408. }
  3409. //
  3410. // We have found a line accepting calls, and we have a free spot in call handle table,
  3411. // so create a call context, add it to TapiProv structures, and notify TAPI of the new
  3412. // call
  3413. //
  3414. do
  3415. {
  3416. HDRV_CALL hdCall;
  3417. //
  3418. // Create a call context
  3419. //
  3420. if ( ALLOC_CALL( &pCall ) != NDIS_STATUS_SUCCESS )
  3421. {
  3422. status = NDIS_STATUS_RESOURCES;
  3423. break;
  3424. }
  3425. //
  3426. // Initialize the call context
  3427. //
  3428. status = TpCallInitialize( pCall, pLine, (HTAPI_CALL) 0, TRUE /* fIncoming */ );
  3429. if ( status != NDIS_STATUS_SUCCESS )
  3430. break;
  3431. //
  3432. // Insert the call context into the tapi provider's handle table
  3433. //
  3434. hdCall = (HDRV_CALL) InsertToHandleTable( pAdapter->TapiProv.hCallTable,
  3435. (USHORT) nIndex,
  3436. (PVOID) pCall );
  3437. if ( hdCall == (HDRV_CALL) NULL )
  3438. {
  3439. status = NDIS_STATUS_TAPI_CALLUNAVAIL;
  3440. break;
  3441. }
  3442. fCallInsertedToHandleTable = TRUE;
  3443. //
  3444. // Set the call's hdCall member
  3445. //
  3446. pCall->hdCall = hdCall;
  3447. //
  3448. // Insert the call context into the line's active call list
  3449. //
  3450. NdisAcquireSpinLock( &pLine->lockLine );
  3451. InsertHeadList( &pLine->linkCalls, &pCall->linkCalls );
  3452. pLine->nActiveCalls++;
  3453. ReferenceLine( pLine, FALSE );
  3454. NdisReleaseSpinLock( &pLine->lockLine );
  3455. //
  3456. // Reference the call 3 times:
  3457. // 1. For running FsmReceiveCall() below
  3458. // 2. For dropping of the call
  3459. // 3. For closing of the call
  3460. //
  3461. NdisAcquireSpinLock( &pCall->lockCall );
  3462. ReferenceCall( pCall, FALSE );
  3463. ReferenceCall( pCall, FALSE );
  3464. ReferenceCall( pCall, FALSE );
  3465. NdisReleaseSpinLock( &pCall->lockCall );
  3466. status = NDIS_STATUS_SUCCESS;
  3467. } while ( FALSE );
  3468. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  3469. //
  3470. // Check the status
  3471. //
  3472. if ( status == NDIS_STATUS_SUCCESS )
  3473. {
  3474. //
  3475. // Kick the state machine to start receiving the call
  3476. //
  3477. FsmReceiveCall( pCall, pBinding, pPacket );
  3478. //
  3479. // Remove the reference added above
  3480. //
  3481. DereferenceCall( pCall );
  3482. }
  3483. else
  3484. {
  3485. //
  3486. // If something failed, do clean up
  3487. //
  3488. if ( fCallInsertedToHandleTable )
  3489. {
  3490. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  3491. RemoveFromHandleTable( pAdapter->TapiProv.hCallTable, (NDIS_HANDLE) pCall->hdCall );
  3492. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  3493. }
  3494. if ( pCall )
  3495. {
  3496. TpCallCleanup( pCall );
  3497. }
  3498. }
  3499. TRACE( TL_N, TM_Tp, ("-TpReceiveCall=$%x",status) );
  3500. }
  3501. BOOLEAN
  3502. TpIndicateNewCall(
  3503. IN CALL* pCall
  3504. )
  3505. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3506. Functional Description:
  3507. This function will be called to indicate the new call context to to TAPI.
  3508. If TAPI can be notified succesfully, then it returns TRUE, otherwise it
  3509. returns FALSE.
  3510. Parameters:
  3511. pCall _ New call context to be indicated to TAPI.
  3512. Return Values:
  3513. TRUE
  3514. FALSE
  3515. ---------------------------------------------------------------------------*/
  3516. {
  3517. NDIS_TAPI_EVENT TapiEvent;
  3518. BOOLEAN fRet = FALSE;
  3519. TRACE( TL_N, TM_Tp, ("+TpIndicateNewCall") );
  3520. NdisAcquireSpinLock( &pCall->lockCall );
  3521. if ( pCall->ulClFlags & CLBF_CallDropped ||
  3522. pCall->ulClFlags & CLBF_CallClosePending )
  3523. {
  3524. TRACE( TL_N, TM_Tp, ("TpIndicateNewCall: Can not indicate new call since call is going down") );
  3525. TRACE( TL_N, TM_Tp, ("-TpIndicateNewCall") );
  3526. //
  3527. // This may happen if call is closed internally due to the FSM timeout handlers
  3528. //
  3529. NdisReleaseSpinLock( &pCall->lockCall );
  3530. return fRet;
  3531. }
  3532. NdisReleaseSpinLock( &pCall->lockCall );
  3533. //
  3534. // Indicate the new call to TAPI, retrieve the corresponding TAPI handle (htCall)
  3535. // and set it in the call
  3536. //
  3537. // Future: The casts below between ulParam2. pCall->hdCall and pCall->htCall will
  3538. // be a problem on 64 bit machines.
  3539. //
  3540. TapiEvent.htLine = pCall->pLine->htLine;
  3541. TapiEvent.htCall = 0;
  3542. TapiEvent.ulMsg = LINE_NEWCALL;
  3543. TapiEvent.ulParam1 = (ULONG) pCall->hdCall;
  3544. TapiEvent.ulParam2 = 0;
  3545. TapiEvent.ulParam3 = 0;
  3546. TRACE( TL_N, TM_Tp, ("TpIndicateNewCall: Indicate LINE_NEWCALL") );
  3547. NdisMIndicateStatus( pCall->pLine->pAdapter->MiniportAdapterHandle,
  3548. NDIS_STATUS_TAPI_INDICATION,
  3549. &TapiEvent,
  3550. sizeof( NDIS_TAPI_EVENT ) );
  3551. NdisAcquireSpinLock( &pCall->lockCall );
  3552. pCall->htCall = (HTAPI_CALL) TapiEvent.ulParam2;
  3553. fRet = TRUE;
  3554. NdisReleaseSpinLock( &pCall->lockCall );
  3555. TRACE( TL_N, TM_Tp, ("-TpIndicateNewCall") );
  3556. return fRet;
  3557. }