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.

3116 lines
124 KiB

  1. /*
  2. (C) Copyright 1999
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the same terms
  7. outlined in the Microsoft Windows Device Driver Development Kit.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL CallMgr CallMgr_c
  12. @module CallMgr.c |
  13. This module defines the interface to the <t CALL_MANAGER_OBJECT>.
  14. Supports the interface between NDISPROXY and the Miniport. All the
  15. Address Family, SAP, VC, and call related events pass through these
  16. interface on their way to and from NDPROXY.
  17. @comm
  18. This module will require some changes depending on how your hardware
  19. works. But in general, you should try to isolate your changes down in
  20. <f DChannel\.c> and <f Card\.c>.
  21. @head3 Contents |
  22. @index class,mfunc,func,msg,mdata,struct,enum | CallMgr_c
  23. @end
  24. */
  25. /* @doc EXTERNAL INTERNAL
  26. @topic 3.1 Call Manager Interface |
  27. The NDPROXY driver is a provider for the Windows Telephony service.
  28. Applications make TAPI requests and the Windows Telephony service routes
  29. these requests to NDPROXY. NDPROXY implements the Telephony Service Provider
  30. Interface (TSPI) for the Windows Telephony service. NDPROXY then
  31. communicates through NDIS with the NDISWAN driver and CoNDIS WAN miniport
  32. drivers. These CoNDIS WAN miniport drivers must provide TAPI capability.
  33. The NDPROXY driver passes TAPI requests by encapsulating TAPI parameters in
  34. NDIS structures. NDPROXY presents a client interface to CoNDIS WAN miniport
  35. drivers and a call manager interface to NDISWAN. NDISWAN presents a client
  36. interface to NDPROXY. CoNDIS WAN miniport drivers present a call manager
  37. interface to NDPROXY and a CoNDIS miniport interface to NDISWAN.
  38. A TAPI-capable CoNDIS WAN miniport driver registers and initializes itself
  39. as a user of both WAN and TAPI services. After registration and
  40. initialization are complete, a user-level application can make telephonic
  41. requests to the Windows Telephony service module, which converts TAPI
  42. requests to TSPI requests. The Windows Telephony service module passes these
  43. requests to the NDPROXY driver. NDPROXY encapsulates parameters for TAPI
  44. requests in NDIS structures and routes the requests to the appropriate
  45. CoNDIS WAN miniport driver. These requests are routed in order to set up,
  46. monitor, and tear down lines, and calls.
  47. A TAPI-capable CoNDIS WAN miniport driver can also communicate changes in
  48. the states of lines and calls, for instance the arrival of an incoming call
  49. or a remote disconnection.
  50. @ex Registering and opening the TAPI address family between NDPROXY and MCM |
  51. NDPROXY NDIS MCM
  52. |----------------------------------|----------------------------------|
  53. | | NdisMCmRegisterAddressFamily |
  54. | ProtocolCoAfRegisterNotify |---------------------------------|
  55. |---------------------------------| |
  56. | NdisClOpenAddressFamily | |
  57. |---------------------------------| ProtocolCmOpenAf |
  58. | |---------------------------------|
  59. | | CompleteCmOpenAf |
  60. | | NdisCmOpenAddressFamilyComplete |
  61. | ProtocolOpenAfComplete |---------------------------------|
  62. |---------------------------------| |
  63. |----------------------------------|----------------------------------|
  64. @ex Closing the TAPI address family between NDPROXY and MCM |
  65. NDPROXY NDIS MCM
  66. |----------------------------------|----------------------------------|
  67. | NdisClCloseAddressFamily | |
  68. |---------------------------------| ProtocolCmCloseAf |
  69. | |---------------------------------|
  70. | | CompleteCmCloseAf |
  71. | | NdisMCmCloseAddressFamilyComplete|
  72. | ProtocolClCloseAfComplete |---------------------------------|
  73. |---------------------------------| |
  74. |----------------------------------|----------------------------------|
  75. @ex Registering a SAP between NDPROXY and MCM |
  76. NDPROXY NDIS MCM
  77. |----------------------------------|----------------------------------|
  78. | NdisClRegisterSap | |
  79. |---------------------------------| ProtocolCmRegisterSap |
  80. | |---------------------------------|
  81. | | CompleteCmRegisterSap |
  82. | | NdisMCmRegisterSapComplete |
  83. | ProtocolClRegisterSapComplete |---------------------------------|
  84. |---------------------------------| |
  85. |----------------------------------|----------------------------------|
  86. @ex Deregistering a SAP between NDPROXY and MCM |
  87. NDPROXY NDIS MCM
  88. |----------------------------------|----------------------------------|
  89. | NdisClDeregisterSap | |
  90. |---------------------------------| ProtocolCmDeregisterSap |
  91. | |---------------------------------|
  92. | | CompleteCmDeregisterSap |
  93. | | NdisMCmDeregisterSapComplete |
  94. | ProtocolClDeregisterSapComplete |---------------------------------|
  95. |---------------------------------| |
  96. |----------------------------------|----------------------------------|
  97. @ex Seting up an outgoing call from NDPROXY to MCM |
  98. NDPROXY NDIS MCM
  99. |----------------------------------|----------------------------------|
  100. | NdisCoCreateVc | ProtocolCoCreateVC |
  101. |---------------------------------|--------------------------------|
  102. | NdisClMakeCall | ProtocolCmMakeCall |
  103. |---------------------------------|---------------------------------|
  104. | . | . |
  105. | . | . |
  106. | . | . |
  107. | | NdisMCmActivateVC |
  108. | |---------------------------------|
  109. | | ProtocolCmActivateVcComplete |
  110. | |---------------------------------|
  111. | ProtocolClMakeCallComplete | NdisMCmMakeCallComplete |
  112. |--------------------------------|---------------------------------|
  113. | . | . |
  114. | . "Tranmit & receive packets" . |
  115. | . | . |
  116. | "Client/MCM initiated call termination" |
  117. | NdisCoDeleteVc | ProtocolCoDeleteVc |
  118. |---------------------------------|--------------------------------|
  119. |----------------------------------|----------------------------------|
  120. @ex Setting up an incoming call from MCM to NDPROXY |
  121. NDPROXY NDIS MCM
  122. |----------------------------------|----------------------------------|
  123. | NdisCoCreateVc | NdisMCmCreateVC |
  124. |--------------------------------|---------------------------------|
  125. | | NdisMCmActivateVC |
  126. | |---------------------------------|
  127. | | ProtocolCmActivateVcComplete |
  128. | |---------------------------------|
  129. | ProtocolClIncomingCall | NdisMCmDispatchIncomingCall |
  130. |---------------------------------|---------------------------------|
  131. | | |
  132. | NdisClIncomingCallComplete | ProtocolCmIncomingCallComplete |
  133. |---------------------------------|--------------------------------|
  134. | ProtocolClCallConnected | NdisMCmDispatchCallConnected |
  135. |--------------------------------|---------------------------------|
  136. | . | . |
  137. | . "Tranmit & receive packets" . |
  138. | . | . |
  139. | "Client/MCM initiated call termination" |
  140. | ProtocolCoDeleteVc | NdisMCmDeleteVc |
  141. |--------------------------------|---------------------------------|
  142. |----------------------------------|----------------------------------|
  143. @ex NDPROXY initiated call termination |
  144. NDPROXY NDIS MCM
  145. |----------------------------------|----------------------------------|
  146. | NdisClCloseCall | ProtocolCmCloseCall |
  147. |---------------------------------|---------------------------------|
  148. | | NdisMCmDeactivateVc |
  149. | |---------------------------------|
  150. | | ProtocolCmDeactivateVcComplete |
  151. | |---------------------------------|
  152. | ProtocolClCloseCallComplete | NdisCmCloseCallComplete |
  153. |--------------------------------|---------------------------------|
  154. |----------------------------------|----------------------------------|
  155. @ex MCM initiated call termination |
  156. NDPROXY NDIS MCM
  157. |----------------------------------|----------------------------------|
  158. | ProtocolClIncomingCloseCall | NdisMCmDispatchIncomingCloseCall |
  159. |---------------------------------|---------------------------------|
  160. | NdisClCloseCall | ProtocolCmCloseCall |
  161. |---------------------------------|---------------------------------|
  162. | | NdisMCmDeactivateVc |
  163. | |---------------------------------|
  164. | | ProtocolCmDeactivateVcComplete |
  165. | |---------------------------------|
  166. | ProtocolClCloseCallComplete | NdisCmCloseCallComplete |
  167. |--------------------------------|---------------------------------|
  168. |----------------------------------|----------------------------------|
  169. @end
  170. */
  171. #define __FILEID__ CALL_MANAGER_OBJECT_TYPE
  172. // Unique file ID for error logging
  173. #include "Miniport.h" // Defines all the miniport objects
  174. #if defined(NDIS_LCODE)
  175. # pragma NDIS_LCODE // Windows 9x wants this code locked down!
  176. # pragma NDIS_LDATA
  177. #endif
  178. BOOLEAN ReferenceSap(
  179. IN PMINIPORT_ADAPTER_OBJECT pAdapter,
  180. IN PBCHANNEL_OBJECT pBChannel
  181. )
  182. {
  183. BOOLEAN bResult;
  184. NdisAcquireSpinLock(&pAdapter->EventLock);
  185. if(pBChannel->SapRefCount > 0)
  186. {
  187. ASSERT(pBChannel->NdisSapHandle);
  188. pBChannel->SapRefCount++;
  189. bResult = TRUE;
  190. }
  191. else
  192. {
  193. bResult = FALSE;
  194. }
  195. NdisReleaseSpinLock(&pAdapter->EventLock);
  196. return bResult;
  197. }
  198. VOID DereferenceSap(
  199. IN PMINIPORT_ADAPTER_OBJECT pAdapter,
  200. IN PBCHANNEL_OBJECT pBChannel
  201. )
  202. {
  203. LONG lRef;
  204. NdisAcquireSpinLock(&pAdapter->EventLock);
  205. lRef = --pBChannel->SapRefCount;
  206. ASSERT(pBChannel->NdisSapHandle);
  207. ASSERT(pBChannel->SapRefCount >= 0);
  208. NdisReleaseSpinLock(&pAdapter->EventLock);
  209. if(lRef == 0)
  210. {
  211. CompleteCmDeregisterSap(pBChannel, NDIS_STATUS_SUCCESS);
  212. }
  213. }
  214. /* @doc INTERNAL CallMgr CallMgr_c CompleteCmOpenAf
  215. @func
  216. <f CompleteCmOpenAf> is called when the miniport is done processing the
  217. <f ProtocolCmOpenAf> request.
  218. @comm
  219. If you return NDIS_STATUS_PENDING from <f ProtocolCmOpenAf>, you must
  220. call <f CompleteCmOpenAf> so that <f NdisMCmOpenAddressFamilyComplete>
  221. can be called to complete the request.
  222. */
  223. VOID CompleteCmOpenAf(
  224. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  225. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  226. // <f AdapterCreate>.
  227. IN NDIS_STATUS Status // @parm
  228. // The NDIS status code to be passed to NdisMCmOpenAddressFamilyComplete.
  229. )
  230. {
  231. DBG_FUNC("CompleteCmOpenAf")
  232. DBG_ENTER(pAdapter);
  233. /*
  234. // Try to connect to the DChannel.
  235. */
  236. DChannelOpen(pAdapter->pDChannel);
  237. NdisMCmOpenAddressFamilyComplete(Status, pAdapter->NdisAfHandle, pAdapter);
  238. DBG_LEAVE(pAdapter);
  239. }
  240. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmOpenAf
  241. @func
  242. <f ProtocolCmOpenAf> is a required function that allocates per-open
  243. resources for a call manager to interact with a connection-oriented NDIS
  244. client that is opening the address family.
  245. @comm
  246. ProtocolCmOpenAf performs any required allocations of dynamic resources
  247. and structures that the call manager writer deems necessary to perform
  248. operations on behalf of the client that is opening an instance of this
  249. address family. Such resources include, but are not limited to, memory
  250. buffers, data structures, events, and other such similar resources. A call
  251. manager should also initialize any relevant per-open data before returning
  252. control to NDIS.
  253. When a call manager has allocated its per-open state area, the address of
  254. the state area should be set in the CallMgrAfContext handle before returning
  255. control to NDIS. To do this, dereference CallMgrAfContext and store a
  256. pointer to the data area as the value of the handle. For example:
  257. *CallMgrAfContext = SomeBuffer; // We use <t MINIPORT_ADAPTER_OBJECT>.
  258. If ProtocolCmOpenAf cannot allocate the per-open resources it needs to
  259. carry out subsequent requests on behalf of the client opening this address
  260. family, it should free all resources that it allocated for the open and
  261. return control to the NDIS with NDIS_STATUS_RESOURCES.
  262. If ProtocolCmOpenAf has completed its required operations and the CM is
  263. ready to accept requests from the client, ProtocolCmOpenAf should return
  264. control as quickly as possible with a status of NDIS_STATUS_SUCCESS.
  265. ProtocolCmOpenAf must be written so that it can run at IRQL DISPATCH_LEVEL.
  266. @rdesc
  267. ProtocolCmOpenAf returns the status of its operation(s) as one of the
  268. following:
  269. @rvalue NDIS_STATUS_SUCCESS |
  270. Indicates that the call manager has successfully allocated and initialized
  271. any resources necessary to accept requests from the client to this address
  272. family.
  273. @rvalue NDIS_STATUS_PENDING |
  274. Indicates that the requested operation is being handled asynchronously. The
  275. call manager must call NdisCmOpenAddressFamilyComplete when it has completed
  276. all its open-AF operations to indicate to NDIS (and the client) that the
  277. operation(s) has been completed.
  278. @rvalue NDIS_STATUS_RESOURCES |
  279. Indicates that the call manager could not complete its necessary
  280. operation(s) because of a lack of available system resources, such as
  281. memory.
  282. @rvalue NDIS_STATUS_XXX |
  283. Indicates that the call manager could not set itself into a state where it
  284. can accept requests from the client to operate on this address family. This
  285. could be an error status propagated from another NDIS library function or
  286. any error status determined appropriate by the driver writer.
  287. @xref
  288. NdisClOpenAddressFamily, NdisCmOpenAddressFamilyComplete,
  289. NdisCmRegisterAddressFamily, NdisOpenAdapter, <f ProtocolCmCloseAf>
  290. */
  291. NDIS_STATUS ProtocolCmOpenAf(
  292. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  293. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  294. // <f AdapterCreate>. AKA CallMgrBindingContext.<nl>
  295. // Specifies the handle to a call manager-allocated context area in which
  296. // the call managers maintains its per-binding state information. The call
  297. // manager supplied this handle when it called NdisOpenAdapter.
  298. IN PCO_ADDRESS_FAMILY AddressFamily, // @parm
  299. // Specifies the address family that a client is opening. This address
  300. // family was registered by the call manager when it called
  301. // NdisCmRegisterAddressFamily.
  302. IN NDIS_HANDLE NdisAfHandle, // @parm
  303. // Specifies a handle, supplied by NDIS, that uniquely identifies this
  304. // address family instance. This handle is opaque to the call manager and
  305. // reserved for system use.
  306. OUT PNDIS_HANDLE CallMgrAfContext // @parm
  307. // Specifies the handle to a call manager-supplied context area in which
  308. // the call manager maintains state about this open of an address family it
  309. // provides.
  310. )
  311. {
  312. DBG_FUNC("ProtocolCmOpenAf")
  313. NDIS_STATUS Status;
  314. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  315. DBG_ENTER(pAdapter);
  316. if (pAdapter->NdisAfHandle != NULL)
  317. {
  318. // Our AF has already been opened and it doesn't make any sense to
  319. // accept another since there is no way to distinguish which should
  320. // receive incoming calls.
  321. DBG_ERROR(pAdapter, ("Attempting to open AF again!\n"));
  322. Status = NDIS_STATUS_FAILURE;
  323. }
  324. else
  325. {
  326. pAdapter->NdisAfHandle = NdisAfHandle;
  327. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  328. ("TAPI AF=0x%X AddressFamily=0x%X MajorVersion=0x%X MinorVersion=0x%X\n",
  329. NdisAfHandle,
  330. AddressFamily->AddressFamily,
  331. AddressFamily->MajorVersion,
  332. AddressFamily->MinorVersion
  333. ));
  334. // Since we return NDIS_STATUS_PENDING here, we must call
  335. // NdisMCmOpenAddressFamilyComplete to complete this request.
  336. // If necessary, you can do the completion asynchronously.
  337. *CallMgrAfContext = pAdapter;
  338. CompleteCmOpenAf(pAdapter, NDIS_STATUS_SUCCESS);
  339. Status = NDIS_STATUS_PENDING;
  340. }
  341. DBG_RETURN(pAdapter, Status);
  342. return (Status);
  343. }
  344. /* @doc INTERNAL CallMgr CallMgr_c CompleteCmCloseAf
  345. @func
  346. <f CompleteCmCloseAf> is called when the miniport is done processing the
  347. <f ProtocolCmCloseAf> request.
  348. @comm
  349. If you return NDIS_STATUS_PENDING from <f ProtocolCmCloseAf>, you must
  350. call <f CompleteCmCloseAf> so that <f NdisMCmCloseAddressFamilyComplete>
  351. can be called to complete the request.
  352. */
  353. VOID CompleteCmCloseAf(
  354. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  355. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  356. // <f AdapterCreate>.
  357. IN NDIS_STATUS Status // @parm
  358. // The NDIS status code to be passed to NdisMCmCloseAddressFamilyComplete.
  359. )
  360. {
  361. DBG_FUNC("CompleteCmCloseAf")
  362. NDIS_HANDLE NdisAfHandle;
  363. DBG_ENTER(pAdapter);
  364. NdisAfHandle = pAdapter->NdisAfHandle;
  365. pAdapter->NdisAfHandle = NULL;
  366. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  367. ("TAPI AF=0x%X\n",
  368. NdisAfHandle));
  369. NdisMCmCloseAddressFamilyComplete(Status, NdisAfHandle);
  370. DBG_LEAVE(pAdapter);
  371. }
  372. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmCloseAf
  373. @func
  374. <f ProtocolCmCloseAf> is a required function that releases per-open
  375. resources for an address family that a call manager supports.
  376. @comm
  377. ProtocolCmCloseAf releases and/or deactivates any resources that were
  378. allocated by the call manager in its ProtocolCmOpenAf function. The call
  379. manager also should undo any other actions it took on behalf of the
  380. connection-oriented client when the address family was opened by that
  381. client.
  382. If there are any outstanding requests or connections still open on an
  383. address family stored in the CallMgrAfContext, a call manager can respond to
  384. a client's request to close the address family in either of the following
  385. ways:
  386. The call manager can fail the request with NDIS_STATUS_NOT_ACCEPTED.
  387. The call manager can return NDIS_STATUS_PENDING. After the client has closed
  388. all calls and deregistered all SAPs, the call manager can then close the
  389. address family and call Ndis(M)CmCloseAddressFamilyComplete to notify the
  390. client. This is the preferred response.
  391. ProtocolCmCloseAf must be written so that it can run at IRQL DISPATCH_LEVEL.
  392. @rdesc
  393. ProtocolCmCloseAf returns the status of its operation(s) as one of the
  394. following:
  395. @rvalue NDIS_STATUS_SUCCESS |
  396. Indicates that the call manager has successfully released or deactivated any
  397. resources that is allocated on behalf of the connection-oriented client that
  398. opened this instance of the address family.
  399. @rvalue NDIS_STATUS_PENDING |
  400. Indicates that the request to close the open instance of the address family
  401. will be completed asynchronously. The call manager must call
  402. NdisCmCloseAddressFamilyComplete when all such operations have been
  403. completed.
  404. @xref
  405. NdisCmCloseAddressFamilyComplete, <f ProtocolCmOpenAf>
  406. */
  407. NDIS_STATUS ProtocolCmCloseAf(
  408. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  409. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  410. // <f ProtocolCmOpenAf>. AKA CallMgrAfContext.<nl>
  411. // Specifies the handle to the call manager's per-AF context area,
  412. // originally supplied to NDIS by the call manager's ProtocolCmOpenAf
  413. // function.
  414. )
  415. {
  416. DBG_FUNC("ProtocolCmCloseAf")
  417. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  418. // Holds the result code returned by this function.
  419. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  420. DBG_ENTER(pAdapter);
  421. // Since we return NDIS_STATUS_PENDING here, we must call
  422. // NdisMCmCloseAddressFamilyComplete to complete this request.
  423. // TODO: If necessary, you can do the completion asynchronously.
  424. DChannelClose(pAdapter->pDChannel);
  425. CompleteCmCloseAf(pAdapter, NDIS_STATUS_SUCCESS);
  426. Result = NDIS_STATUS_PENDING;
  427. DBG_RETURN(pAdapter, Result);
  428. return (Result);
  429. }
  430. VOID CompleteCmRegisterSap(
  431. IN PBCHANNEL_OBJECT pBChannel, // @parm
  432. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  433. IN NDIS_STATUS Status // @parm
  434. // The NDIS status code to be passed to NdisMCmRegisterSapComplete.
  435. )
  436. {
  437. DBG_FUNC("CompleteCmRegisterSap")
  438. PMINIPORT_ADAPTER_OBJECT pAdapter;
  439. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  440. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  441. pAdapter = pBChannel->pAdapter;
  442. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  443. DBG_ENTER(pAdapter);
  444. /*
  445. // TODO: What statistics do you want to collect and report?
  446. */
  447. pAdapter->TotalRxBytes = 0;
  448. pAdapter->TotalTxBytes = 0;
  449. pAdapter->TotalRxPackets = 0;
  450. pAdapter->TotalTxPackets = 0;
  451. // If you return NDIS_STATUS_PENDING from ProtocolCmRegisterSap, you
  452. // must call NdisMCmRegisterSapComplete to complete the request.
  453. NdisMCmRegisterSapComplete(Status, pBChannel->NdisSapHandle, pBChannel);
  454. DBG_LEAVE(pAdapter);
  455. }
  456. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmRegisterSap
  457. @func
  458. <f ProtocolCmRegisterSap> is a required function that is called by NDIS to
  459. request that a call manager register a SAP (service access point) on behalf
  460. of a connection-oriented client.
  461. @comm
  462. ProtocolCmRegisterSap communicates with network control devices or other
  463. media-specific agents, as necessary, to register the SAP, as specified at
  464. Sap, on the network for a connection-oriented client. Such actions could
  465. include, but are not limited to communicating with switching hardware,
  466. communicating with a network control station, or other actions that are
  467. appropriate to the network medium.
  468. If a call manager is required to communicate with networking control agents
  469. (e.g. a network switch) it should use a virtual connection to the network
  470. control agent that it established in its ProtocolBindAdapter function.
  471. Standalone call managers communicate through the underlying NIC miniport by
  472. calling NdisCoSendPackets. NIC miniports with integrated call-management
  473. support never call NdisCoSendPackets. Instead, they transmit the data
  474. directly across the network.
  475. In addition, ProtocolCmRegisterSap should perform any necessary allocations
  476. of dynamic resources and structures that the call manager needs to maintain
  477. state information about the SAP on behalf of the connection-oriented client.
  478. Such resources include, but are not limited to, memory buffers, data
  479. structures, events, and other such similar resources. A call manager must
  480. also initialize any resources it allocates before returning control to NDIS.
  481. Call managers must store the NDIS-supplied handle identifying the SAP,
  482. provided at NdisSapHandle, in their context area for future use.
  483. If ProtocolCmRegisterSap will return NDIS_STATUS_SUCCESS, it should, after
  484. allocating the per-SAP state area, set the address of this state area in
  485. CallMgrSapContext before returning control to NDIS. To do this, dereference
  486. CallMgrSapContext and store a pointer to the data area as the value of the
  487. handle. For example:
  488. *CallMgrSapContext = SomeBuffer; // We use <t BCHANNEL_OBJECT>.
  489. If the given SAP that is already registered by another connection-oriented
  490. client, the call manager must fail the request and return
  491. NDIS_STATUS_INVALID_DATA.
  492. After a call manager has registered a SAP on behalf of a connection-oriented
  493. client, it notifies that client of an incoming call offer directed to that
  494. SAP by calling NdisCmDispatchIncomingCall.
  495. ProtocolCmRegisterSap must be written so that it can run at IRQL DISPATCH_LEVEL.
  496. @rdesc
  497. ProtocolCmRegisterSap returns the status of its operation(s) as one of the
  498. following:
  499. @rvalue NDIS_STATUS_SUCCESS |
  500. Indicates that the call manager successfully allocated and/or initialized
  501. any necessary resources to register and maintain the SAP. In addition, it
  502. also indicates that the SAP was registered successfully as required by the
  503. network media that the call manager supports.
  504. @rvalue NDIS_STATUS_PENDING |
  505. Indicates that the call manager will complete the processing of this request
  506. asynchronously. Call managers must call NdisCmRegisterSapComplete when all
  507. processing has been completed to signal NDIS that the registration is
  508. finished.
  509. @rvalue NDIS_STATUS_RESOURCES |
  510. Indicates that the call manager was unable to allocated and/or initialize
  511. its resources required to register the SAP on behalf of the
  512. connection-oriented client.
  513. @rvalue NDIS_STATUS_INVALID_DATA |
  514. Indicates that the specification provided at Sap is invalid or cannot be
  515. supported.
  516. @rvalue NDIS_STATUS_XXX |
  517. Indicates that the call manager encountered an error in attempting to
  518. register the SAP for the connection-oriented client. The return code is
  519. appropriate to the error and could be a return code propagated from another
  520. NDIS library function.
  521. @xref
  522. NdisCmDispatchIncomingCall, NdisCmRegisterSapComplete, NdisCoSendPackets,
  523. <f ProtocolCmDeregisterSap>, <f ProtocolCmOpenAf>
  524. */
  525. NDIS_STATUS ProtocolCmRegisterSap(
  526. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  527. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  528. // <f ProtocolCmOpenAf>. AKA CallMgrAfContext.<nl>
  529. // Specifies the handle to a call-manager allocated context area in which
  530. // the call manager maintains its per-open AF state. The call manager
  531. // supplied this handle to NDIS from its ProtocolCmOpenAf function.
  532. IN PCO_SAP Sap, // @parm
  533. // Points to a media-specific CO_SAP structure that contains the specific
  534. // SAP that a connection-oriented client is registering.
  535. IN NDIS_HANDLE NdisSapHandle, // @parm
  536. // Specifies a handle, supplied by NDIS, that uniquely identifies this SAP.
  537. // This handle is opaque to the call manager and reserved for NDIS library
  538. // use.
  539. OUT PNDIS_HANDLE CallMgrSapContext // @parm
  540. // On return, specifies the handle to a call manager-supplied context area
  541. // in which the call manager maintains state about this SAP. We will
  542. // return a pointer to the <t BCHANNEL_OBJECT> instance identified by this
  543. // SAP's lineID.
  544. )
  545. {
  546. DBG_FUNC("ProtocolCmRegisterSap")
  547. PCO_AF_TAPI_SAP pTapiSap = (PCO_AF_TAPI_SAP) Sap->Sap;
  548. PBCHANNEL_OBJECT pBChannel;
  549. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  550. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  551. // Holds the result code returned by this function.
  552. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  553. DBG_ENTER(pAdapter);
  554. if (pTapiSap->ulLineID < pAdapter->NumBChannels)
  555. {
  556. pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter, pTapiSap->ulLineID);
  557. NdisAcquireSpinLock(&pAdapter->EventLock);
  558. if (pBChannel->NdisSapHandle != NULL)
  559. {
  560. NdisReleaseSpinLock(&pAdapter->EventLock);
  561. // A SAP has already been registered and it doesn't make any sense to
  562. // accept another since there are no SAP parameters to distinguish
  563. // them.
  564. DBG_ERROR(pAdapter, ("#%d Attempting to register SAP again!\n",
  565. pBChannel->ObjectID));
  566. Result = NDIS_STATUS_SAP_IN_USE;
  567. }
  568. else
  569. {
  570. pBChannel->NdisSapHandle = NdisSapHandle;
  571. pBChannel->SapRefCount = 1;
  572. ASSERT(Sap->SapType == AF_TAPI_SAP_TYPE);
  573. ASSERT(Sap->SapLength == sizeof(CO_AF_TAPI_SAP));
  574. pBChannel->NdisTapiSap = *pTapiSap;
  575. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  576. ("#%d SAP=0x%X ulLineID=0x%X ulAddressID=0x%X ulMediaModes=0x%X\n",
  577. pBChannel->ObjectID,
  578. NdisSapHandle,
  579. pBChannel->NdisTapiSap.ulLineID,
  580. pBChannel->NdisTapiSap.ulAddressID,
  581. pBChannel->NdisTapiSap.ulMediaModes
  582. ));
  583. // If this BChannel is currently on the available list, move it
  584. // to the end of the list, so listening BChannels can be easily
  585. // allocated to incoming calls from the end of the list.
  586. if (!IsListEmpty(&pBChannel->LinkList))
  587. {
  588. RemoveEntryList(&pBChannel->LinkList);
  589. InsertTailList(&pAdapter->BChannelAvailableList,
  590. &pBChannel->LinkList);
  591. }
  592. NdisReleaseSpinLock(&pAdapter->EventLock);
  593. // Since we return NDIS_STATUS_PENDING here, we must call
  594. // NdisMCmRegisterSapComplete to complete this request.
  595. // TODO: If necessary, you can do the completion asynchronously.
  596. *CallMgrSapContext = pBChannel;
  597. CompleteCmRegisterSap(pBChannel, NDIS_STATUS_SUCCESS);
  598. Result = NDIS_STATUS_PENDING;
  599. }
  600. }
  601. else
  602. {
  603. DBG_ERROR(pAdapter, ("Attempting to register invalid SAP=%d\n",
  604. pTapiSap->ulLineID));
  605. Result = NDIS_STATUS_INVALID_DATA;
  606. }
  607. DBG_RETURN(pAdapter, Result);
  608. return (Result);
  609. }
  610. /* @doc INTERNAL CallMgr CallMgr_c CompleteCmDeregisterSap
  611. @func
  612. <f CompleteCmDeregisterSap> is called when the miniport is done processing
  613. the <f ProtocolCmDeregisterSap> request.
  614. @comm
  615. If you return NDIS_STATUS_PENDING from <f ProtocolCmDeregisterSap>, you
  616. must call <f CompleteCmDeregisterSap> so that
  617. <f NdisMCmDeregisterSapComplete> can be called to complete the request.
  618. */
  619. VOID CompleteCmDeregisterSap(
  620. IN PBCHANNEL_OBJECT pBChannel, // @parm
  621. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  622. IN NDIS_STATUS Status // @parm
  623. // The NDIS status code to be passed to NdisMCmRegisterSapComplete.
  624. )
  625. {
  626. DBG_FUNC("CompleteCmDeregisterSap")
  627. NDIS_HANDLE NdisSapHandle;
  628. PMINIPORT_ADAPTER_OBJECT pAdapter;
  629. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  630. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  631. pAdapter = pBChannel->pAdapter;
  632. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  633. DBG_ENTER(pAdapter);
  634. NdisSapHandle = pBChannel->NdisSapHandle;
  635. NdisAcquireSpinLock(&pAdapter->EventLock);
  636. pBChannel->NdisSapHandle = NULL;
  637. NdisReleaseSpinLock(&pAdapter->EventLock);
  638. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  639. ("#%d SAP=0x%X\n",
  640. pBChannel->ObjectID,
  641. NdisSapHandle
  642. ));
  643. NdisMCmDeregisterSapComplete(Status, NdisSapHandle);
  644. DBG_LEAVE(pAdapter);
  645. }
  646. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmDeregisterSap
  647. @func
  648. <f ProtocolCmDeregisterSap> is a required function that is called by NDIS
  649. to request that a call manager deregister a SAP on behalf of a
  650. connection-oriented client.
  651. @comm
  652. ProtocolCmDeregisterSap communicates with network control devices or other
  653. media-specific agents, as necessary, to deregister the SAP on the network.
  654. Such actions could include, but are not limited to:
  655. Communicating with a switching hardware
  656. Communicating with a network control station
  657. Communicating with other media-specific network agents
  658. If a call manager is required to communicate with networking control agents,
  659. such as a network switch, it should use a virtual connection to the network
  660. control agent that it established in its ProtocolBindAdapter function.
  661. Standalone call managers communicate through the underlying NIC miniport by
  662. calling NdisCoSendPackets. NIC miniports that provide integrated
  663. call-management support never call NdisCoSendPackets. Instead, they transmit
  664. the data directly across the network.
  665. In addition, ProtocolCmDeregisterSap must free any dynamically-allocated
  666. resources in its per-SAP area, provided at CallMgrSapContext, as well as
  667. freeing the state area itself before returning control to NDIS.
  668. ProtocolCmDeregisterSap must be written such that it can be run at IRQL
  669. DISPATCH_LEVEL.
  670. @rdesc
  671. ProtocolCmDeregisterSap returns the status of its operation(s) as one of the
  672. following:
  673. @rvalue NDIS_STATUS_SUCCESS |
  674. Indicates that the call manager successfully removed the SAP registration
  675. and freed any resources allocated to maintain per-SAP information.
  676. @rvalue NDIS_STATUS_PENDING |
  677. Indicates that the call manager will complete the request to deregister the
  678. SAP asynchronously. The call manager must call NdisCmDeregisterSapComplete
  679. to signal NDIS when the operation is complete.
  680. @xref
  681. NdisCmDeregisterSapComplete, NdisCoSendPackets, ProtocolBindAdapter,
  682. <f ProtocolCmRegisterSap>
  683. */
  684. NDIS_STATUS ProtocolCmDeregisterSap(
  685. IN PBCHANNEL_OBJECT pBChannel // @parm
  686. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  687. // <f ProtocolCmRegisterSap>. AKA CallMgrSapContext.<nl>
  688. // Specifies the handle to a call-manager allocated context area in which
  689. // the call manager maintains its per-SAP state information. The call
  690. // manager supplied this handle to NDIS from its ProtocolCmRegisterSap
  691. // function.
  692. )
  693. {
  694. DBG_FUNC("ProtocolCmDeregisterSap")
  695. NDIS_STATUS Result = NDIS_STATUS_PENDING;
  696. // Holds the result code returned by this function.
  697. PMINIPORT_ADAPTER_OBJECT pAdapter;
  698. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  699. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  700. pAdapter = pBChannel->pAdapter;
  701. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  702. DBG_ENTER(pAdapter);
  703. DereferenceSap(pAdapter, pBChannel);
  704. // If you return NDIS_STATUS_PENDING here, you must call
  705. // NdisMCmDeregisterSapComplete to complete this request.
  706. DBG_RETURN(pAdapter, Result);
  707. return (Result);
  708. }
  709. /* @doc EXTERNAL INTERNAL BChannel BChannel_c ProtocolCoCreateVc
  710. @func
  711. <f ProtocolCoCreateVc> is a required function for connection-oriented
  712. miniports. <f ProtocolCoCreateVc> is called by NDIS to indicate to
  713. the miniport that a new VC is being created.
  714. @comm
  715. ProtocolCoCreateVc must be written as a synchronous function and cannot,
  716. under any circumstances, return NDIS_STATUS_PENDING without causing a
  717. system-wide failure.
  718. ProtocolCoCreateVc allocates any necessary resources that the miniport
  719. requires to maintain state information about the VC. The resources could
  720. include, but are not limited to memory buffers, events, data structures,
  721. and other such similar resources.
  722. After allocating all required resources the miniport should initialize the
  723. resources into a usable state and return a pointer to the state area in
  724. MiniportVcContext. The handle is set by dereferencing the handle and
  725. storing a pointer to the state buffer as the value of the handle. For
  726. example:
  727. *MiniportVcContext = SomeBuffer; // We use <t BCHANNEL_OBJECT>.
  728. Miniport drivers must store the handle to the VC, NdisVcHandle, in their
  729. state area as it is a required parameter to other NDIS library routines
  730. that are subsequently called by the miniport.
  731. ProtocolCoCreateVc must be written such that it can be run at IRQL
  732. DISPATCH_LEVEL.
  733. @rdesc
  734. Call managers or clients cannot return NDIS_STATUS_PENDING from their
  735. ProtocolCoCreateVc functions. Returning pending will render this virtual
  736. connection unusable and the NDIS library will call the client or call
  737. manager to delete it.
  738. ProtocolCoCreateVc returns the status of its operation(s) as one of the
  739. following values:
  740. @rvalue NDIS_STATUS_SUCCESS |
  741. Indicates that the call manager or client successfully allocated and/or
  742. initialized any necessary resources that were needed to establish and
  743. maintain a virtual connection.
  744. @rvalue NDIS_STATUS_RESOURCES |
  745. Indicates that the call manager or client was unable to allocate and/or
  746. initialize its resources for establishing and maintaining a virtual
  747. connection.
  748. @rvalue NDIS_STATUS_XXX |
  749. Indicates that the call manager or client could not set itself into a state
  750. where it could establish a virtual connection. This can could be an error
  751. return value propagated from another NDIS library routine.
  752. @xref
  753. <f MiniportInitialize>, NdisMSetAttributes, NdisMSetAttributesEx,
  754. <f ProtocolCoDeleteVc>, <f MiniportCoActivateVc>, <f MiniportCoDeactivateVc>
  755. */
  756. NDIS_STATUS ProtocolCoCreateVc(
  757. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  758. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  759. // <f AdapterCreate>. AKA ProtocolAfContext.<nl>
  760. IN NDIS_HANDLE NdisVcHandle, // @parm
  761. // Specifies a handle, supplied by NDIS, that uniquely identifies
  762. // the VC being created. This handle is opaque to the miniport
  763. // and reserved for NDIS library use.
  764. OUT PBCHANNEL_OBJECT * ppBChannel // @parm
  765. // Specifies, on output, a handle to a miniport-supplied context
  766. // area in which the miniport maintains state about the VC.
  767. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  768. )
  769. {
  770. DBG_FUNC("ProtocolCoCreateVc")
  771. NDIS_STATUS Result = NDIS_STATUS_VC_NOT_AVAILABLE;
  772. // Holds the result code returned by this function.
  773. PBCHANNEL_OBJECT pBChannel = NULL;
  774. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  775. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  776. ASSERT(ppBChannel);
  777. DBG_ENTER(pAdapter);
  778. // Allocate BChannel for VC based on whether it's incoming or outgoing.
  779. #if defined(SAMPLE_DRIVER)
  780. if (NdisVcHandle == NULL)
  781. {
  782. // The calling side has already removed the BChannel from the available
  783. // list, so we just need to use it.
  784. ASSERT(ppBChannel && *ppBChannel && (*ppBChannel)->ObjectType == BCHANNEL_OBJECT_TYPE);
  785. pBChannel = *ppBChannel;
  786. }
  787. else
  788. {
  789. #endif // SAMPLE_DRIVER
  790. NdisAcquireSpinLock(&pAdapter->EventLock);
  791. if (!IsListEmpty(&pAdapter->BChannelAvailableList))
  792. {
  793. if (NdisVcHandle)
  794. {
  795. // Pull from the head of the available list, so we can avoid
  796. // using the BChannels that are setup with listening SAPs at
  797. // the end of the list.
  798. pBChannel = (PBCHANNEL_OBJECT) RemoveHeadList(
  799. &pAdapter->BChannelAvailableList);
  800. // Reset the link info so we can tell that it's not on the list.
  801. InitializeListHead(&pBChannel->LinkList);
  802. }
  803. else
  804. {
  805. // Pull from the tail of the available list, to see if there
  806. // are any listening SAPs that can accept this call.
  807. pBChannel = (PBCHANNEL_OBJECT) RemoveTailList(
  808. &pAdapter->BChannelAvailableList);
  809. // Reset the link info so we can tell that it's not on the list.
  810. InitializeListHead(&pBChannel->LinkList);
  811. if (pBChannel->NdisSapHandle)
  812. {
  813. // TODO: You should look to make sure the incoming call matches
  814. // the SAP of the listener. The sample driver just assumes it.
  815. }
  816. else
  817. {
  818. // Sorry, no one up there wants to hear about it.
  819. InsertTailList(&pAdapter->BChannelAvailableList,
  820. &pBChannel->LinkList);
  821. pBChannel = NULL;
  822. }
  823. }
  824. }
  825. NdisReleaseSpinLock(&pAdapter->EventLock);
  826. #if defined(SAMPLE_DRIVER)
  827. }
  828. #endif // SAMPLE_DRIVER
  829. if (pBChannel == NULL)
  830. {
  831. DBG_ERROR(pAdapter, ("BChannelAvailableList is empty\n"));
  832. }
  833. else if (BChannelOpen(pBChannel, NdisVcHandle) == NDIS_STATUS_SUCCESS)
  834. {
  835. Result = NDIS_STATUS_SUCCESS;
  836. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  837. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  838. pBChannel->ObjectID,
  839. pBChannel->NdisVcHandle, pBChannel->CallState,
  840. Result
  841. ));
  842. }
  843. else
  844. {
  845. // BChannel was already open - this should never happen...
  846. DBG_ERROR(pAdapter,("BChannelOpen failed, but it should be availble\n"));
  847. NdisAcquireSpinLock(&pAdapter->EventLock);
  848. if (NdisVcHandle)
  849. {
  850. // Put it back on the head of the available list.
  851. InsertHeadList(&pAdapter->BChannelAvailableList,
  852. &pBChannel->LinkList);
  853. }
  854. else
  855. {
  856. // Put it back on the tail of the available list.
  857. InsertTailList(&pAdapter->BChannelAvailableList,
  858. &pBChannel->LinkList);
  859. }
  860. NdisReleaseSpinLock(&pAdapter->EventLock);
  861. pBChannel = NULL;
  862. }
  863. *ppBChannel = pBChannel;
  864. DBG_RETURN(pAdapter, Result);
  865. return (Result);
  866. }
  867. /* @doc EXTERNAL INTERNAL BChannel BChannel_c ProtocolCoDeleteVc
  868. @func
  869. <f ProtocolCoDeleteVc> is a required function for connection-oriented
  870. miniports. <f ProtocolCoDeleteVc> indicates that a VC is being torn
  871. down and deleted by NDIS.
  872. @comm
  873. ProtocolCoDeleteVc must be written as a synchronous function and cannot,
  874. under any circumstances, return NDIS_STATUS_PENDING without causing a
  875. system-wide failure.
  876. ProtocolCoDeleteVc frees any resources allocated on a per-VC basis and
  877. stored in the context area MiniportVcContext. The miniport must also free
  878. the MiniportVcContext that is allocated in its ProtocolCoCreateVc
  879. function.
  880. <f ProtocolCoDeleteVc> must be written such that it can be run from IRQL
  881. DISPATCH_LEVEL.
  882. @rdesc
  883. ProtocolCoDeleteVc can return one of the following:
  884. @rvalue NDIS_STATUS_SUCCESS |
  885. The protocol has released or prepared for reuse all the resources that it
  886. originally allocated for the VC.
  887. @rvalue NDIS_STATUS_NOT_ACCEPTED |
  888. The VC is still active and the protocol has outstanding operations pending
  889. on the VC so it could not be destroyed.
  890. @rvalue NDIS_STATUS_XXX |
  891. The protocol failed the VC deletion for a driver-determined reason.
  892. @xref
  893. NdisClCloseCall, NdisCmDispatchIncomingCloseCall, NdisCoCreateVc,
  894. NdisCoDeleteVc, <f ProtocolCoCreateVc>, <f MiniportCoActivateVc>,
  895. <f MiniportCoDeactivateVc>
  896. */
  897. NDIS_STATUS ProtocolCoDeleteVc(
  898. IN PBCHANNEL_OBJECT pBChannel // @parm
  899. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  900. // <f ProtocolCoCreateVc>. AKA ProtocolVcContext.<nl>
  901. // Specifies the handle to the client's or call manager's per-VC context
  902. // area. The protocol originally supplied this handle from its
  903. // <f ProtocolCoCreateVc> function.
  904. )
  905. {
  906. DBG_FUNC("ProtocolCoDeleteVc")
  907. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  908. // Holds the result code returned by this function.
  909. PMINIPORT_ADAPTER_OBJECT pAdapter;
  910. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  911. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  912. pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
  913. DBG_ENTER(pAdapter);
  914. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  915. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  916. pBChannel->ObjectID,
  917. pBChannel->NdisVcHandle, pBChannel->CallState,
  918. Result
  919. ));
  920. BChannelClose(pBChannel);
  921. NdisAcquireSpinLock(&pAdapter->EventLock);
  922. if (pBChannel->NdisSapHandle)
  923. {
  924. // Listening BChannels are kept at the end of the list.
  925. InsertTailList(&pAdapter->BChannelAvailableList, &pBChannel->LinkList);
  926. }
  927. else
  928. {
  929. // Non-listening BChannels are kept at the end of the list.
  930. InsertHeadList(&pAdapter->BChannelAvailableList, &pBChannel->LinkList);
  931. }
  932. NdisReleaseSpinLock(&pAdapter->EventLock);
  933. DBG_RETURN(pAdapter, Result);
  934. return (Result);
  935. }
  936. /* @doc EXTERNAL INTERNAL Link Link_c MiniportCoActivateVc
  937. @func
  938. <f MiniportCoActivateVc> is a required function for connection-oriented
  939. miniports. <f MiniportCoActivateVc> is called by NDIS to indicate to the
  940. miniport that a virtual connection is being activated.
  941. @comm
  942. The miniport driver must validate the call parameters for this VC, as
  943. specified in CallParameters, to verify that the adapter can support the
  944. requested call. If the requested call parameters cannot be satisfied, the
  945. miniport should fail the request with NDIS_STATUS_INVALID_DATA.
  946. MiniportCoActivateVc can be called many times for a single VC in order to
  947. change the call parameters for an already active call. At every call, the
  948. miniport should validate the parameters and perform any processing as
  949. required by its adapter in order to satisfy the request. However, if it
  950. cannot set the given call parameters, MiniportCoActivateVc must leave the
  951. VC in a usable state, because the connection-oriented client or a call
  952. manager can continue to send or receive data using the older call
  953. parameters.
  954. If the ROUND_UP_FLOW or ROUND_DOWN_FLOW flags are set in the call
  955. parameters structure at CallParameters-\>MediaParameters-\>Flags, the
  956. miniport has been requested to return the actual flow rate of the VC after
  957. the flow rate has been rounded according to the appropriate flag that has
  958. been set. If the miniport does change any of the call parameters because
  959. these flags have been set, it must return the actual call parameters in
  960. use for the VC at CallParameters.
  961. If the call parameters are acceptable, MiniportCoActivateVc communicates
  962. with its adapter as necessary to prepare the adapter to receive or
  963. transmit data across the virtual connection (e.g. programming receive
  964. buffers).
  965. MiniportCoActivateVc must be written so that it can be run from IRQL
  966. DISPATCH_LEVEL.
  967. @rdesc
  968. MiniportCoActivateVc can return one of the following:
  969. @rvalue NDIS_STATUS_SUCCESS |
  970. Indicates that the VC was activated successfully.
  971. @rvalue NDIS_STATUS_PENDING |
  972. Indicates that the miniport will complete the request to activate a VC
  973. asynchronously. When the miniport has finished with its operations, it must
  974. call NdisMCoActivateVcComplete.
  975. @rvalue NDIS_STATUS_INVALID_DATA |
  976. Indicates that the call parameters specified at CallParameters are invalid
  977. or illegal for the media type that this miniport supports.
  978. @rvalue NDIS_STATUS_RESOURCES |
  979. Indicates that the miniport could not activate the VC because it could not
  980. allocate all of the required resources that the miniport needs to maintain
  981. state information about the active VC.
  982. @xref
  983. <f ProtocolCoCreateVc>, <f MiniportCoDeactivateVc>, NdisMCoActivateVcComplete
  984. */
  985. NDIS_STATUS MiniportCoActivateVc(
  986. IN PBCHANNEL_OBJECT pBChannel, // @parm
  987. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  988. // <f ProtocolCoCreateVc>. AKA MiniportVcContext.<nl>
  989. // Specifies the handle to a miniport-allocated context area in which the
  990. // miniport maintains its per-VC state. The miniport supplied this handle
  991. // to NDIS from its <f ProtocolCoCreateVc> function.
  992. IN OUT PCO_CALL_PARAMETERS pCallParameters // @parm
  993. // A pointer to the <t CO_CALL_PARAMETERS>
  994. // Specifies the call parameters, as specified by the call manager, to be
  995. // established for this VC. On output, the miniport returns altered call
  996. // parameters if certain flags are set in the CO_CALL_PARAMETERS structure.
  997. )
  998. {
  999. DBG_FUNC("MiniportCoActivateVc")
  1000. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1001. // Holds the result code returned by this function.
  1002. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1003. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1004. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1005. pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
  1006. DBG_ENTER(pAdapter);
  1007. // TODO: Add code here if needed
  1008. DBG_RETURN(pAdapter, Result);
  1009. return (Result);
  1010. }
  1011. /* @doc EXTERNAL INTERNAL Link Link_c MiniportCoDeactivateVc
  1012. @func
  1013. <f MiniportCoDeactivateVc> is a required function for connection-oriented
  1014. miniports. <f MiniportCoDeactivateVc> is called by NDIS to indicate that
  1015. a VC is being marked as unusable.
  1016. @comm
  1017. MiniportCoDeactivateVc communicates with its network adapter to terminate
  1018. all communication across this VC (e.g. deprogramming receive or send buffers
  1019. on the adapter). The miniport should also mark the VC, it its context area,
  1020. as being inactive to prevent any further communication across the VC.
  1021. There is not a one-to-one relationship between calls to MiniportCoActivateVc
  1022. and MiniportCoDeactivateVc. While NDIS may call MiniportCoActivateVc
  1023. multiple times on a single VC, only one call to MiniportCoDeactivateVc is
  1024. made to shut down a virtual connection. For example, a VC can be reused for
  1025. different calls possibly causing multiple calls to MiniportCoActivateVc.
  1026. @rdesc
  1027. MiniportCoDeactivateVc can return one of the following:
  1028. @rvalue NDIS_STATUS_SUCCESS |
  1029. Indicates that the miniport successfully halted any communication across the
  1030. VC and marked it as unusable.
  1031. @rvalue NDIS_STATUS_PENDING |
  1032. Indicates that the miniport will complete the request to halt the VC
  1033. asynchronously. When the miniport has completed halting the VC, it must then
  1034. call NdisMCoDeactivateVcComplete to signal NDIS that this operation has been
  1035. completed.
  1036. @xref
  1037. <f MiniportCoActivateVc>, NdisMCoDeactivateVcComplete
  1038. */
  1039. NDIS_STATUS MiniportCoDeactivateVc(
  1040. IN PBCHANNEL_OBJECT pBChannel // @parm
  1041. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1042. // <f ProtocolCoCreateVc>. AKA MiniportVcContext.<nl>
  1043. // Specified the handle to a miniport-allocated context area in which the
  1044. // miniport maintains state information per-VC. The miniport supplied this
  1045. // handle to NDIS from its <f ProtocolCoCreateVc> function.
  1046. )
  1047. {
  1048. DBG_FUNC("MiniportCoDeactivateVc")
  1049. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1050. // Holds the result code returned by this function.
  1051. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1052. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1053. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1054. pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
  1055. DBG_ENTER(pAdapter);
  1056. // TODO: Add code here if needed
  1057. DBG_RETURN(pAdapter, Result);
  1058. return (Result);
  1059. }
  1060. /* @doc INTERNAL CallMgr CallMgr_c CompleteCmMakeCall
  1061. @func
  1062. <f CompleteCmMakeCall> is called when the miniport is done processing the
  1063. <f ProtocolCmMakeCall> request.
  1064. @comm
  1065. If you return NDIS_STATUS_PENDING from <f ProtocolCmMakeCall>, you must
  1066. call <f CompleteCmMakeCall> so that <f NdisMCmMakeCallComplete>
  1067. can be called to complete the request.
  1068. This routine also activates the VC and marks the call state as connected.
  1069. */
  1070. VOID CompleteCmMakeCall(
  1071. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1072. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  1073. IN NDIS_STATUS Status // @parm
  1074. // Status to return to <f NdisMCmMakeCallComplete>. If status does not
  1075. // equal NDIS_STATUS_SUCCESS, the call is closed and the BChannel is
  1076. // released.
  1077. )
  1078. {
  1079. DBG_FUNC("CompleteCmMakeCall")
  1080. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1081. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1082. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1083. pAdapter = pBChannel->pAdapter;
  1084. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1085. DBG_ENTER(pAdapter);
  1086. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1087. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  1088. pBChannel->ObjectID,
  1089. pBChannel->NdisVcHandle, pBChannel->CallState,
  1090. Status
  1091. ));
  1092. if (Status == NDIS_STATUS_SUCCESS)
  1093. {
  1094. pBChannel->pOutCallParms->CallMgrParameters->Receive.PeakBandwidth =
  1095. pBChannel->pOutCallParms->CallMgrParameters->Transmit.PeakBandwidth =
  1096. pBChannel->LinkSpeed/8;
  1097. Status = NdisMCmActivateVc(pBChannel->NdisVcHandle,
  1098. pBChannel->pOutCallParms);
  1099. if (Status == NDIS_STATUS_SUCCESS)
  1100. {
  1101. pBChannel->Flags |= VCF_VC_ACTIVE;
  1102. pBChannel->CallState = LINECALLSTATE_CONNECTED;
  1103. }
  1104. else
  1105. {
  1106. DBG_ERROR(pAdapter,("NdisMCmActivateVc Error=0x%X\n",Status));
  1107. }
  1108. }
  1109. NdisMCmMakeCallComplete(Status, pBChannel->NdisVcHandle,
  1110. NULL, NULL,
  1111. pBChannel->pOutCallParms);
  1112. if (Status != NDIS_STATUS_SUCCESS)
  1113. {
  1114. // The call failed, so cleanup and bail out.
  1115. pBChannel->Flags &= ~VCF_OUTGOING_CALL;
  1116. }
  1117. DBG_LEAVE(pAdapter);
  1118. }
  1119. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmMakeCall
  1120. @func
  1121. <f ProtocolCmMakeCall> is a required function that sets up media specific
  1122. parameters for a virtual connection (VC) and activates the virtual
  1123. connection.
  1124. @comm
  1125. If ProtocolCmMakeCall is given an explicit NdisPartyHandle, this VC was
  1126. created by the client for a multipoint call. The call manager must allocate
  1127. and initialize any necessary resources required to maintain state
  1128. information and control a multipoint call. Such resources include, but are
  1129. not limited to, memory buffers, data structures, events, and other similar
  1130. resources. If the call manager cannot allocate or initialize the needed
  1131. resources for its state area(s), it should return control to NDIS with
  1132. NDIS_STATUS_RESOURCES.
  1133. ProtocolCmMakeCall communicates with network control devices or other
  1134. media-specific actors, as necessary, to make a connection between the local
  1135. node and a remote node based on the call parameters specified at
  1136. CallParameters. Such actions could include, but are not limited to,
  1137. communication with switching hardware, communications with a network control
  1138. station, or other actions as appropriate to the network medium.
  1139. If a call manager is required to communication with networking hardware
  1140. (e.g. a networking switch) it should use a virtual connection to the network
  1141. control device that it established in its ProtocolBindAdapter function. Call
  1142. managers communicate with their network hardware through the miniport driver
  1143. by calling NdisCoSendPackets. NIC miniports with integrated call-management
  1144. support will not call NdisCoSendPackets, but rather will transmit the data
  1145. themselves.
  1146. After a call manager has done all necessary communication with its
  1147. networking hardware as required by its medium, call managers must call
  1148. NdisCmActivateVc.
  1149. If this call was a multipoint call, after the call manager has communicated
  1150. with the networking hardware, verified call parameters, and allocated and
  1151. initialized its per-party state data, the address of its state block should
  1152. be set in the handle CallMgrPartyContext before returning control to NDIS.
  1153. The handle is set by dereferencing the handle and storing a pointer to the
  1154. state block as the value of the handle. For example:
  1155. *CallMgrPartyContext = SomeBuffer; // We use NULL
  1156. If ProtocolCmMakeCall has completed the required operations for its network
  1157. and the VC has been successfully activated through NdisCmActivateVc,
  1158. ProtocolCmMakeCall should return control as quickly as possible with a
  1159. status of NDIS_STATUS_SUCCESS.
  1160. After ProtocolCmMakeCall returns control to NDIS, the call manager should
  1161. expect to take no further actions on this call to set it up.
  1162. ProtocolCmMakeCall is responsible for establishing the connection so that
  1163. the client can make data transfers over the network on this VC. However, the
  1164. call manager can be called subsequently to modify the call's quality of
  1165. service, to add or drop parties if this is a multipoint VC, and eventually
  1166. to terminate this call.
  1167. ProtocolCmMakeCall must be written so that it can run at IRQL
  1168. DISPATCH_LEVEL.
  1169. @rdesc
  1170. <f ProtocolCmMakeCall> returns the status of its operation(s) as one of
  1171. the following values:
  1172. @rvalue NDIS_STATUS_SUCCESS |
  1173. Indicates that the call manager successfully allocated the necessary
  1174. resources to make the call and was able to activate the virtual connection
  1175. with the miniport driver.
  1176. @rvalue NDIS_STATUS_PENDING |
  1177. Indicates that the call manager will complete the request to make a call
  1178. asynchronously. When the call manager has completed all operations for
  1179. making a call, it must call NdisCmMakeCallComplete to signal NDIS that this
  1180. call has been completed.
  1181. @rvalue NDIS_STATUS_RESOURCES |
  1182. Indicates that the call manager was unable to allocate and/or initialize its
  1183. resources for activating the virtual connection as requested by the client.
  1184. @rvalue NDIS_STATUS_NOT_SUPPORTED |
  1185. Indicates that the call manager was unable to activate a virtual connection
  1186. because the caller requested invalid or unavailable features in the call
  1187. parameters specified at CallParameters.
  1188. @xref
  1189. NdisClMakeCall, NdisCmActivateVc, NdisCmMakeCallComplete,
  1190. <f ProtocolCoCreateVc>
  1191. */
  1192. NDIS_STATUS ProtocolCmMakeCall(
  1193. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1194. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1195. // <f ProtocolCoCreateVc>. AKA CallMgrVcContext.<nl>
  1196. // Specifies the handle to a call manager-allocated context area in which
  1197. // the call managers maintains its per-VC state. The call manager supplied
  1198. // this handle to NDIS from its ProtocolCoCreateVc function.
  1199. IN OUT PCO_CALL_PARAMETERS pCallParameters, // @parm
  1200. // Points to a CO_CALL_PARAMETERS structure that contains the parameters,
  1201. // specified by a connection-oriented client, for this outgoing call.
  1202. IN NDIS_HANDLE NdisPartyHandle, // @parm
  1203. // Specifies a handle, supplied by NDIS, that uniquely identifies the
  1204. // initial party on the multipoint virtual connection. This handle is
  1205. // opaque to the call manager and reserved for NDIS library use. This
  1206. // handle is NULL if the client is not setting up an outgoing multipoint
  1207. // call.
  1208. OUT PNDIS_HANDLE CallMgrPartyContext // @parm
  1209. // On return, specifies a handle to a call manager-supplied context area in
  1210. // which the call manager maintains state about the initial party on the
  1211. // multipoint call. If NdisPartyHandle is NULL, this handle must be set to
  1212. // NULL.
  1213. )
  1214. {
  1215. DBG_FUNC("ProtocolCmMakeCall")
  1216. PCO_AF_TAPI_MAKE_CALL_PARAMETERS pTapiCallParameters;
  1217. // Points to the TAPI call parameters contained in pCallParameters.
  1218. PLINE_CALL_PARAMS pLineCallParams;
  1219. // Points to the LINE call parameters contained in pTapiCallParameters.
  1220. USHORT DialStringLength;
  1221. // Length of the dial string in bytes.
  1222. PUSHORT pDialString;
  1223. // Points to the dial string contained in pTapiCallParameters.
  1224. UCHAR DialString[CARD_MAX_DIAL_DIGITS+1];
  1225. // Temporary copy of dial string. One extra for NULL terminator.
  1226. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1227. // Holds the result code returned by this function.
  1228. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1229. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1230. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1231. pAdapter = pBChannel->pAdapter;
  1232. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1233. DBG_ENTER(pAdapter);
  1234. // Check a few preconditions ;) Maybe the NDPROXY will change the rules
  1235. // someday, and we'll have to change our assumptions...
  1236. ASSERT(NdisPartyHandle == NULL);
  1237. ASSERT(pCallParameters->Flags == 0);
  1238. ASSERT(pCallParameters->CallMgrParameters);
  1239. ASSERT(pCallParameters->CallMgrParameters->Transmit.TokenRate ==
  1240. pBChannel->LinkSpeed/8);
  1241. ASSERT(pCallParameters->CallMgrParameters->Receive.TokenRate ==
  1242. pBChannel->LinkSpeed/8);
  1243. ASSERT(pCallParameters->CallMgrParameters->CallMgrSpecific.ParamType == 0);
  1244. ASSERT(pCallParameters->CallMgrParameters->CallMgrSpecific.Length == 0);
  1245. ASSERT(pCallParameters->MediaParameters);
  1246. ASSERT(pCallParameters->MediaParameters->Flags & TRANSMIT_VC);
  1247. ASSERT(pCallParameters->MediaParameters->Flags & RECEIVE_VC);
  1248. ASSERT(pCallParameters->MediaParameters->ReceiveSizeHint >=
  1249. pAdapter->pCard->BufferSize);
  1250. ASSERT(pCallParameters->MediaParameters->MediaSpecific.ParamType == 0);
  1251. ASSERT(pCallParameters->MediaParameters->MediaSpecific.Length >=
  1252. sizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS));
  1253. pTapiCallParameters = (PCO_AF_TAPI_MAKE_CALL_PARAMETERS)
  1254. pCallParameters->MediaParameters->MediaSpecific.Parameters;
  1255. ASSERT(pTapiCallParameters->ulLineID < pAdapter->NumBChannels);
  1256. ASSERT(pTapiCallParameters->ulAddressID == TSPI_ADDRESS_ID);
  1257. ASSERT(pTapiCallParameters->ulFlags & CO_TAPI_FLAG_OUTGOING_CALL);
  1258. ASSERT(pTapiCallParameters->DestAddress.Length > sizeof(USHORT));
  1259. ASSERT(pTapiCallParameters->DestAddress.MaximumLength >=
  1260. pTapiCallParameters->DestAddress.Length);
  1261. ASSERT(pTapiCallParameters->DestAddress.Offset >=
  1262. sizeof(NDIS_VAR_DATA_DESC));
  1263. DialStringLength = pTapiCallParameters->DestAddress.Length;
  1264. pDialString = (PUSHORT)
  1265. ((PUCHAR)&pTapiCallParameters->DestAddress +
  1266. pTapiCallParameters->DestAddress.Offset);
  1267. ASSERT(pTapiCallParameters->LineCallParams.Length >= sizeof(LINE_CALL_PARAMS));
  1268. ASSERT(pTapiCallParameters->LineCallParams.MaximumLength >=
  1269. pTapiCallParameters->LineCallParams.Length);
  1270. ASSERT(pTapiCallParameters->LineCallParams.Offset >=
  1271. sizeof(NDIS_VAR_DATA_DESC));
  1272. pLineCallParams = (PLINE_CALL_PARAMS)
  1273. ((PUCHAR)&pTapiCallParameters->LineCallParams +
  1274. pTapiCallParameters->LineCallParams.Offset);
  1275. // This was useful for debugging the nested call parameter structures.
  1276. DBG_NOTICE(pAdapter,(
  1277. "\t\tsizeof(CO_CALL_PARAMETERS) =%03d\n"
  1278. "\t\tsizeof(CO_CALL_MANAGER_PARAMETERS) =%03d\n"
  1279. "\t\tsizeof(CO_MEDIA_PARAMETERS) =%03d\n"
  1280. "\t\tsizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS) =%03d\n"
  1281. "\t\tsizeof(LINE_CALL_PARAMS) =%03d\n",
  1282. "\t\tMaximumLength =%03d\n",
  1283. sizeof(CO_CALL_PARAMETERS),
  1284. sizeof(CO_CALL_MANAGER_PARAMETERS),
  1285. sizeof(CO_MEDIA_PARAMETERS),
  1286. sizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS),
  1287. sizeof(LINE_CALL_PARAMS),
  1288. pTapiCallParameters->LineCallParams.MaximumLength
  1289. ));
  1290. /*
  1291. // TODO: The sample driver doesn't support multi-party calls.
  1292. */
  1293. *CallMgrPartyContext = NULL;
  1294. /*
  1295. // Make sure the call parameters are valid for us.
  1296. */
  1297. if (pLineCallParams->ulBearerMode & ~pBChannel->BearerModesCaps)
  1298. {
  1299. DBG_WARNING(pAdapter, ("TAPI_INVALBEARERMODE=0x%X\n",
  1300. pLineCallParams->ulBearerMode));
  1301. Result = NDIS_STATUS_NOT_SUPPORTED;
  1302. }
  1303. else if (pLineCallParams->ulMediaMode & ~pBChannel->MediaModesCaps)
  1304. {
  1305. DBG_WARNING(pAdapter, ("TAPI_INVALMEDIAMODE=0x%X\n",
  1306. pLineCallParams->ulMediaMode));
  1307. Result = NDIS_STATUS_NOT_SUPPORTED;
  1308. }
  1309. else if (pLineCallParams->ulMinRate > _64KBPS ||
  1310. pLineCallParams->ulMinRate > pLineCallParams->ulMaxRate)
  1311. {
  1312. DBG_WARNING(pAdapter, ("TAPI_INVALRATE=%d:%d\n",
  1313. pLineCallParams->ulMinRate,pLineCallParams->ulMaxRate));
  1314. Result = NDIS_STATUS_NOT_SUPPORTED;
  1315. }
  1316. else if (pLineCallParams->ulMaxRate && pLineCallParams->ulMaxRate < _56KBPS)
  1317. {
  1318. DBG_WARNING(pAdapter, ("TAPI_INVALRATE=%d:%d\n",
  1319. pLineCallParams->ulMinRate,pLineCallParams->ulMaxRate));
  1320. Result = NDIS_STATUS_NOT_SUPPORTED;
  1321. }
  1322. else if (DialStringLength == 0)
  1323. {
  1324. DBG_WARNING(pAdapter, ("TAPI_INVALPARAM=No dial string\n"));
  1325. Result = NDIS_STATUS_NOT_SUPPORTED;
  1326. }
  1327. else
  1328. {
  1329. /*
  1330. // Dial the number, but don't include the null terminator.
  1331. */
  1332. DialStringLength = CardCleanPhoneNumber(DialString,
  1333. pDialString,
  1334. DialStringLength);
  1335. if (DialStringLength > 0)
  1336. {
  1337. /*
  1338. // Save the call parameters.
  1339. */
  1340. pBChannel->MediaMode = pLineCallParams->ulMediaMode;
  1341. pBChannel->BearerMode = pLineCallParams->ulBearerMode;
  1342. pBChannel->LinkSpeed = pLineCallParams->ulMaxRate == 0 ?
  1343. _64KBPS : pLineCallParams->ulMaxRate;
  1344. pBChannel->pOutCallParms = pCallParameters;
  1345. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1346. ("#%d VC=0x%X CallState=0x%X DIALING: '%s'\n"
  1347. "\tLineID=%d - AddressID=%d - "
  1348. "Rate=%d-%d - MediaMode=0x%X - BearerMode=0x%X\n",
  1349. pBChannel->ObjectID,
  1350. pBChannel->NdisVcHandle, pBChannel->CallState,
  1351. DialString,
  1352. pTapiCallParameters->ulLineID,
  1353. pTapiCallParameters->ulAddressID,
  1354. pLineCallParams->ulMinRate,
  1355. pLineCallParams->ulMaxRate,
  1356. pLineCallParams->ulMediaMode,
  1357. pLineCallParams->ulBearerMode
  1358. ));
  1359. // Now we're ready to tell the network about the call.
  1360. Result = DChannelMakeCall(pAdapter->pDChannel,
  1361. pBChannel,
  1362. DialString,
  1363. DialStringLength,
  1364. pLineCallParams);
  1365. if (Result != NDIS_STATUS_PENDING)
  1366. {
  1367. CompleteCmMakeCall(pBChannel, Result);
  1368. Result = NDIS_STATUS_PENDING;
  1369. }
  1370. }
  1371. else
  1372. {
  1373. DBG_WARNING(pAdapter, ("TAPI_INVALPARAM=Invalid dial string=%s\n",
  1374. pDialString));
  1375. Result = NDIS_STATUS_NOT_SUPPORTED;
  1376. }
  1377. }
  1378. DBG_RETURN(pAdapter, Result);
  1379. return (Result);
  1380. }
  1381. /* @doc INTERNAL CallMgr CallMgr_c CompleteCmCloseCall
  1382. @func
  1383. <f CompleteCmCloseCall> is called when the miniport is done processing the
  1384. <f ProtocolCmCloseCall> request.
  1385. @comm
  1386. If you return NDIS_STATUS_PENDING from <f ProtocolCmCloseCall>, you must
  1387. call <f CompleteCmCloseCall> so that <f NdisMCmCloseCallComplete>
  1388. can be called to complete the request.
  1389. Upon return from this routine, you can no longer access the BChannel/VC
  1390. as it has been deactivated and returned to the available pool.
  1391. */
  1392. VOID CompleteCmCloseCall(
  1393. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1394. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1395. // <f ProtocolCoCreateVc>.
  1396. IN NDIS_STATUS Status // @parm
  1397. // Status to return to <f NdisMCmCloseCallComplete>. Regardless of the
  1398. // status, the VC is deactivated and deleted.
  1399. )
  1400. {
  1401. DBG_FUNC("CompleteCmCloseCall")
  1402. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1403. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1404. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1405. pAdapter = pBChannel->pAdapter;
  1406. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1407. DBG_ENTER(pAdapter);
  1408. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1409. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  1410. pBChannel->ObjectID,
  1411. pBChannel->NdisVcHandle, pBChannel->CallState, Status
  1412. ));
  1413. // Deactivate the VC if needed.
  1414. if (pBChannel->Flags & VCF_VC_ACTIVE)
  1415. {
  1416. pBChannel->Flags &= ~VCF_VC_ACTIVE;
  1417. NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
  1418. }
  1419. // Tell NDPROXY we're done.
  1420. NdisMCmCloseCallComplete(Status, pBChannel->NdisVcHandle, NULL);
  1421. // If it was an incoming call, it's up to us to delete the VC.
  1422. if (pBChannel->Flags & VCF_INCOMING_CALL)
  1423. {
  1424. pBChannel->Flags &= ~VCF_INCOMING_CALL;
  1425. if (pBChannel->NdisVcHandle)
  1426. {
  1427. NdisMCmDeleteVc(pBChannel->NdisVcHandle);
  1428. pBChannel->NdisVcHandle = NULL;
  1429. ProtocolCoDeleteVc((NDIS_HANDLE) pBChannel);
  1430. }
  1431. }
  1432. else if (pBChannel->Flags & VCF_OUTGOING_CALL)
  1433. {
  1434. pBChannel->Flags &= ~VCF_OUTGOING_CALL;
  1435. }
  1436. DBG_LEAVE(pAdapter);
  1437. }
  1438. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmCloseCall
  1439. @func
  1440. <f ProtocolCmCloseCall> is a required function that terminates an existing
  1441. call and releases any resources that the call manager allocated for the
  1442. call.
  1443. @comm
  1444. ProtocolCmCloseCall communicated with network control devices or other
  1445. media-specific actors, as necessitated by its media, to terminate a
  1446. connection between the local node and a remote node. If the call manager is
  1447. required to communicate with network control devices (e.g. a networking
  1448. switch) it should use a virtual connection to the network control device
  1449. that it established in its ProtocolBindAdapter function. Standalone call
  1450. managers communicate to such network devices by calling NdisCoSendPackets.
  1451. NIC miniports with integrated call-management support never call
  1452. NdisCoSendPackets. Instead, they transmit the data directly across the
  1453. network.
  1454. If CloseData is nonNULL and sending data at connection termination is
  1455. supported by the media that this call manager handles, the call manager
  1456. should transmit the data specified at CloseData to the remote node before
  1457. completing the call termination. If sending data concurrent with a
  1458. connection being terminated is not supported, call managers should return
  1459. NDIS_STATUS_INVALID_DATA.
  1460. If ProtocolCmCloseCall is passed an explicit CallMgrPartyContext, then the
  1461. call being terminated is a multipoint VC, and the call manager must perform
  1462. any necessary network communication with its networking hardware, as
  1463. appropriate to its media type, to terminate the call as a multipoint call.
  1464. The call manager must also free the memory that it allocated earlier, in
  1465. ProtocolCmMakeCall, for its per-party state that is pointed to by
  1466. CallMgrPartyContext. Failure to properly release, de-allocate, or otherwise
  1467. deactivate those resources causes a memory leak.
  1468. After the call has been terminated with the network, any close data has been
  1469. sent, and any resources at CallMgrPartyContext have been freed, the call
  1470. manager must call NdisCmDeactivateVc. This notifies NDIS and the underlying
  1471. NIC miniport, if any, to expect no further transfers on the given VC.
  1472. ProtocolCmCloseCall must be written so that it can run at IRQL
  1473. DISPATCH_LEVEL.
  1474. @rdesc
  1475. ProtocolCmCloseCall returns the status of its operation(s) as one of the
  1476. following:
  1477. @rvalue NDIS_STATUS_SUCCESS |
  1478. Indicates that the call manager successfully terminated the call.
  1479. @rvalue NDIS_STATUS_PENDING |
  1480. Indicates that the call manager will complete the request to terminate the
  1481. call asynchronously. When the call manager has completed all operations
  1482. required to terminate the connection, it must then call
  1483. NdisCmCloseCallComplete to signal NDIS that the call has been closed.
  1484. @rvalue NDIS_STATUS_INVALID_DATA |
  1485. Indicates that CloseData was specified, but the underlying network medium
  1486. does not support sending data concurrent with terminating a call.
  1487. @rvalue NDIS_STATUS_XXX |
  1488. Indicates that the call manager could not terminate the call. The actual
  1489. error returned can be a status propagated from another NDIS library routine.
  1490. @xref
  1491. NdisClMakeCall, NdisCmDeactivateVc, NdisCoSendPackets,
  1492. <f ProtocolCmMakeCall>
  1493. */
  1494. NDIS_STATUS ProtocolCmCloseCall(
  1495. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1496. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1497. // <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
  1498. // Specifies the handle to a call manager-allocated context area in which
  1499. // the call manager maintains its per-VC state. This handle was provided to
  1500. // NDIS from the call managers <f ProtocolCmMakeCall> function.
  1501. IN NDIS_HANDLE CallMgrPartyContext, // @parm
  1502. // Specifies the handle, if any, to a call manager-allocated context area
  1503. // in which the call manager maintain information about a party on a
  1504. // multipoint VC. This handle is NULL if the call being closed is not a
  1505. // multipoint call.
  1506. IN PVOID CloseData, // @parm
  1507. // Points to a buffer containing connection-oriented client-specified data
  1508. // that should be sent across the connection before the call is terminated.
  1509. // This parameter is NULL if the underlying network medium does not support
  1510. // transfers of data when closing a connection.
  1511. IN UINT Size // @parm
  1512. // Specifies the length, in bytes, of the buffer at CloseData, zero if
  1513. // CloseData is NULL.
  1514. )
  1515. {
  1516. DBG_FUNC("ProtocolCmCloseCall")
  1517. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1518. // Holds the result code returned by this function.
  1519. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1520. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1521. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1522. pAdapter = pBChannel->pAdapter;
  1523. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1524. DBG_ENTER(pAdapter);
  1525. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1526. ("#%d VC=0x%X CallState=0x%X\n",
  1527. pBChannel->ObjectID,
  1528. pBChannel->NdisVcHandle, pBChannel->CallState
  1529. ));
  1530. Result = DChannelCloseCall(pAdapter->pDChannel, pBChannel);
  1531. if (Result != NDIS_STATUS_PENDING)
  1532. {
  1533. CompleteCmCloseCall(pBChannel, Result);
  1534. Result = NDIS_STATUS_PENDING;
  1535. }
  1536. DBG_RETURN(pAdapter, Result);
  1537. return (Result);
  1538. }
  1539. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmIncomingCallComplete
  1540. @func
  1541. <f ProtocolCmIncomingCallComplete> is a required function that, when called
  1542. by NDIS, indicates to the call manager that the connection-oriented client
  1543. has finished processing of an incoming call offer that the call manager
  1544. previously dispatched through NdisCmDispatchIncomingCall.
  1545. @comm
  1546. When the connection-oriented client has completed processing of an incoming
  1547. connection offer that the call manager dispatched to it, this routine will
  1548. be called if NdisCmDispatchIncomingCall returned NDIS_STATUS_PENDING. The
  1549. final status of the incoming call is found in Status. Possible values for
  1550. Status include, but are not limited to:
  1551. @flag NDIS_STATUS_SUCCESS |
  1552. Indicates that the call manager has accepted the incoming call.
  1553. @flag NDIS_STATUS_FAILURE |
  1554. Indicates that either the address family or the SAP that the call dispatched
  1555. for is currently in the process of closing.
  1556. @flag NDIS_STATUS_RESOURCES |
  1557. Indicates that the incoming call was not accepted because the
  1558. connection-oriented client was unable to dynamically allocate resources
  1559. required for it to process the call.
  1560. @flag NDIS_STATUS_INVALID_DATA |
  1561. Indicates that the connection-oriented client rejected the call because the
  1562. call parameters specified were invalid.
  1563. @normal
  1564. If the client accepts the incoming call, the call manager should send
  1565. signaling message(s) to indicate to the calling entity that the call has
  1566. been accepted. If the client does not accept the call, the call manager
  1567. should send signaling message(s) to indicate that the call has been
  1568. rejected.
  1569. ProtocolCmIncomingCallComplete must be written so that is can be run at IRQL
  1570. DISPATCH_LEVEL.
  1571. @xref
  1572. NdisCmDispatchIncomingCall, ProtocolClIncomingCall, <f ProtocolCmRegisterSap>
  1573. */
  1574. VOID ProtocolCmIncomingCallComplete(
  1575. IN NDIS_STATUS Status, // @parm
  1576. // Indicates the final status of the operation to dispatch an incoming call
  1577. // to a connection-oriented client.
  1578. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1579. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1580. // <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
  1581. // Specifies the handle to a call manager-allocated context area in which
  1582. // the call manager maintains its per-VC state. The call manager supplied
  1583. // this handle from its <f ProtocolCoCreateVc> function.
  1584. IN PCO_CALL_PARAMETERS pCallParameters // @parm
  1585. // Points to the call parameters as specified by the call manager in the
  1586. // call to NdisCmDispatchIncomingCall. The signaling protocol determines
  1587. // which call parameters, if any, the call manager can change.
  1588. )
  1589. {
  1590. DBG_FUNC("ProtocolCmIncomingCallComplete")
  1591. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1592. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1593. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1594. pAdapter = pBChannel->pAdapter;
  1595. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1596. DBG_ENTER(pAdapter);
  1597. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1598. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  1599. pBChannel->ObjectID,
  1600. pBChannel->NdisVcHandle, pBChannel->CallState, Status
  1601. ));
  1602. if (Status != NDIS_STATUS_SUCCESS)
  1603. {
  1604. // We're not going to answer this call.
  1605. DChannelRejectCall(pAdapter->pDChannel, pBChannel);
  1606. if (pBChannel->Flags & VCF_VC_ACTIVE)
  1607. {
  1608. pBChannel->Flags &= ~VCF_VC_ACTIVE;
  1609. NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
  1610. }
  1611. if (pBChannel->NdisVcHandle)
  1612. {
  1613. NdisMCmDeleteVc(pBChannel->NdisVcHandle);
  1614. pBChannel->NdisVcHandle = NULL;
  1615. ProtocolCoDeleteVc((NDIS_HANDLE) pBChannel);
  1616. }
  1617. }
  1618. else
  1619. {
  1620. Status = DChannelAnswerCall(pAdapter->pDChannel, pBChannel);
  1621. if (Status == NDIS_STATUS_SUCCESS)
  1622. {
  1623. pBChannel->CallState = LINECALLSTATE_CONNECTED;
  1624. NdisMCmDispatchCallConnected(pBChannel->NdisVcHandle);
  1625. }
  1626. else if (Status != NDIS_STATUS_PENDING)
  1627. {
  1628. InitiateCallTeardown(pAdapter, pBChannel);
  1629. }
  1630. }
  1631. DBG_LEAVE(pAdapter);
  1632. }
  1633. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmActivateVcComplete
  1634. @func
  1635. <f ProtocolCmActivateVcComplete> is a required function that indicates to
  1636. the call manager that a previous call to NdisCoActivateVc has been completed
  1637. by the miniport.
  1638. @comm
  1639. When other network components have completed their operations for activating
  1640. a virtual connection, initiated when the call manager called
  1641. NdisCmActivateVc, NDIS notifies the call manager that the VC has been
  1642. activated by calling its ProtocolCmActivateVcComplete function. The status
  1643. of the activation is found in Status. Possible values for Status include,
  1644. but are not limited to:
  1645. @flag NDIS_STATUS_SUCCESS |
  1646. Indicates that the VC completed successfully and the call manager can
  1647. continue operations on this VC as required by its media.
  1648. @flag NDIS_STATUS_RESOURCES |
  1649. Indicates that another component in the activation has failed to activate
  1650. the virtual connection because of a lack of memory or an inability allocate
  1651. another type of resource.
  1652. @flag NDIS_STATUS_NOT_ACCEPTED |
  1653. Indicates that an activation is currently pending on the virtual connection.
  1654. Only one activation can be processed at a time for a virtual connection. The
  1655. request to activate the VC should be tried again at a later time.
  1656. @flag NDIS_STATUS_CLOSING |
  1657. Indicates that a deactivation is pending on the VC and the VC is no longer
  1658. available for network communication until the deactivation has been
  1659. completed and a successful activation has taken place.
  1660. @flag NDIS_STATUS_INVALID_DATA |
  1661. Indicates that the miniport has rejected the call parameters at
  1662. CallParamters as invalid for the adapter.
  1663. @normal
  1664. ProtocolCmActivateVcComplete must check the status returned in Status to
  1665. ensure that the virtual connection has been activated successfully. The call
  1666. manager must not attempt to communicate over the virtual connection if
  1667. Status is not NDIS_STATUS_SUCCESS.
  1668. Call managers must complete any processing required by their network media
  1669. to ensure that the virtual connection is ready for data transmission before
  1670. returning control to NDIS.
  1671. If the call manager specified either ROUND_UP_FLOW or ROUND_DOWN_FLOW in the
  1672. CallParameters->MediaParamters->Flags, the call parameters returned in
  1673. CallParamters can have been changed by the miniport. Call managers should
  1674. examine the call parameters that were returned to ensure proper operation.
  1675. If the new call parameters are unsatisfactory, the call manager should
  1676. either call NdisCmActivateVc again with new call parameters or deactivate
  1677. the VC with NdisCmDeactivateVc.
  1678. ProtocolCmActivateVcComplete must be written so that it can run at IRQL
  1679. DISPATCH_LEVEL.
  1680. @xref
  1681. NdisCmActivateVc, NdisCmDeactivateVc, <f ProtocolCmMakeCall>
  1682. */
  1683. VOID ProtocolCmActivateVcComplete(
  1684. IN NDIS_STATUS Status, // @parm
  1685. // Specifies the final status, as indicated by the miniport, of the request
  1686. // by the call manager to activate a VC.
  1687. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1688. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1689. // <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
  1690. // Specifies the handle to a call manager-allocated context area in which
  1691. // the call manager maintains its per-VC state. The call manager supplied
  1692. // this handle from its <f ProtocolCoCreateVc> function.
  1693. IN PCO_CALL_PARAMETERS pCallParameters // @parm
  1694. // Points the call parameters as specified by the call manager in a call to
  1695. // NdisCmActivateVc.
  1696. )
  1697. {
  1698. DBG_FUNC("ProtocolCmActivateVcComplete")
  1699. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1700. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1701. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1702. pAdapter = pBChannel->pAdapter;
  1703. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1704. DBG_ENTER(pAdapter);
  1705. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1706. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  1707. pBChannel->ObjectID,
  1708. pBChannel->NdisVcHandle, pBChannel->CallState, Status
  1709. ));
  1710. DBG_LEAVE(pAdapter);
  1711. }
  1712. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmDeactivateVcComplete
  1713. @func
  1714. <f ProtocolCmDeactivateVcComplete> is a required function that completes the
  1715. processing of a call-manager initiated request that the underlying miniport
  1716. (and NDIS) deactivate a VC for which NdisCmDeactivateVc previously returned
  1717. NDIS_STATUS_PENDING.
  1718. @comm
  1719. NDIS usually calls ProtocolCmDeactivateVcComplete in the context of the call
  1720. manager's closing down a call on behalf of a connection-oriented client. The
  1721. call manager typically calls NdisCmDeactivateVc from its ProtocolCmCloseCall
  1722. function. Whenever NdisCmDeactivateVc returns NDIS_STATUS_PENDING, NDIS
  1723. subsequently calls its ProtocolCmDeactivateVcComplete function.
  1724. That is, when the underlying connection-oriented miniport has deactivated
  1725. the VC, NDIS calls ProtocolCmDeactivateVcComplete. The final status of the
  1726. deactivation is found in Status. Possible values for the final status
  1727. include, but are not limited to:
  1728. @flag NDIS_STATUS_SUCCESS |
  1729. Indicates that the VC was deactivated successfully.
  1730. @flag NDIS_STATUS_NOT_ACCEPTED |
  1731. Indicates that an activation is pending on this VC. The call manager should
  1732. attempt to deactivate the VC at a later time.
  1733. @flag NDIS_STATUS_CLOSING |
  1734. Indicates that a deactivation is currently pending on this VC. The call
  1735. manager need not call NdisCmDeactivateVc again as only one call to
  1736. NdisCmDeactivateVc is required to deactivate a VC.
  1737. @normal
  1738. ProtocolCmDeactivateVcComplete performs whatever postprocessing is necessary
  1739. to complete the deactivation of a virtual connection, such as setting flags
  1740. in its state area to indicate that the connection is inactive or releasing
  1741. dynamically allocated resources used while the VC is active.
  1742. Completion of the deactivation means that all call parameters for the VC
  1743. used on activation are no longer valid. Any further use of the VC is
  1744. prohibited except to reactivate it with a new set of call parameters.
  1745. Call managers should release any resources that were allocated for the VC
  1746. activation and return control as quickly as possible. If the call manager
  1747. previously returned NDIS_STATUS_PENDING from its ProtocolCmCloseCall
  1748. function and all operations to close the call have been completed,
  1749. ProtocolCmDeactivateVcComplete should now call NdisCmCloseCallComplete.
  1750. ProtocolCmDeactivateVcComplete must be written so that it can run at IRQL
  1751. DISPATCH_LEVEL.
  1752. @xref
  1753. <f MiniportCoDeactivateVc>, NdisCmCloseCallComplete, NdisCmDeactivateVc,
  1754. <f ProtocolCmCloseCall>
  1755. */
  1756. VOID ProtocolCmDeactivateVcComplete(
  1757. IN NDIS_STATUS Status, // @parm
  1758. // Specifies the final status of the deactivation.
  1759. IN PBCHANNEL_OBJECT pBChannel // @parm
  1760. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1761. // <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
  1762. // Specifies the handle to a call manager-allocated context area in which
  1763. // the call manager maintains its per-VC state. The call manager supplied
  1764. // this handle from its <f ProtocolCoCreateVc> function.
  1765. )
  1766. {
  1767. DBG_FUNC("ProtocolCmDeactivateVcComplete")
  1768. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1769. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1770. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1771. pAdapter = pBChannel->pAdapter;
  1772. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1773. DBG_ENTER(pAdapter);
  1774. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1775. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  1776. pBChannel->ObjectID,
  1777. pBChannel->NdisVcHandle, pBChannel->CallState, Status
  1778. ));
  1779. DBG_LEAVE(pAdapter);
  1780. }
  1781. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmModifyCallQoS
  1782. @func
  1783. <f ProtocolCmModifyCallQoS> is a required function that is called by NDIS
  1784. when a connection-oriented client requests that the call parameters be
  1785. changed for an existing virtual connection (VC). If the underlying network
  1786. medium does not support QoS, ProtocolCmModifyQoS should simply return
  1787. NDIS_STATUS_NOT_SUPPORTED.
  1788. @comm
  1789. ProtocolCmModifyQoS communicates with network control devices or other
  1790. media-specific agents, as necessitated by its media, to modify the
  1791. media-specific call parameters for an established virtual connection. If the
  1792. call manager is required to communicate with network control agents (e.g. a
  1793. networking switch) it should use a virtual connection to the network control
  1794. agents that it established in its ProtocolBindAdapter function. Standalone
  1795. call managers communicated to the network agents by calling
  1796. NdisCoSendPackets. NIC miniports with integrated call-management support
  1797. never call NdisCoSendPackets. Instead, such a driver simply transfers the
  1798. data over the network to the target network agent.
  1799. After communicating with the network and if the changes were successful, the
  1800. call manager must then call NdisCmActivateVc with the new call parameters.
  1801. This notifies NDIS and/or the connection-oriented miniport that the call
  1802. parameters have changed and provides the miniport with an opportunity to
  1803. validate those parameters.
  1804. If either the network cannot accept the new call parameters or the
  1805. underlying miniport cannot accept the parameters, the call manager must
  1806. restore the virtual connection to the state that existed before any
  1807. modifications were attempted, and return NDIS_STATUS_FAILURE.
  1808. ProtocolCmModifyQoSComplete must be written so that it can run at IRQL
  1809. DISPATCH_LEVEL.
  1810. @rdesc
  1811. ProtocolCmModifyQoS returns the status of its operation(s) as one of the
  1812. following values:
  1813. @rvalue NDIS_STATUS_SUCCESS |
  1814. Indicates that the call manager successfully changed the parameters of the
  1815. call with the network to the call parameters specified at CallParameters.
  1816. @rvalue NDIS_STATUS_PENDING |
  1817. Indicates that the call manager will complete the request to modify the call
  1818. parameters asynchronously. When the call manager has completed all
  1819. operations necessary to modify the call parameters, it must call
  1820. NdisCmModifyCallQoSComplete.
  1821. @rvalue NDIS_STATUS_RESOURCES |
  1822. Indicates that the call manager could not change the call parameters of the
  1823. VC because dynamically allocated resources were not available.
  1824. @rvalue NDIS_STATUS_INVALID_DATA |
  1825. Indicates that the call manager was unable to change the call parameters of
  1826. the VC because the call parameters provided at CallParameters were illegal
  1827. or invalid.
  1828. @rvalue NDIS_STATUS_FAILURE |
  1829. Indicates that the call parameters could not be set to the call parameters
  1830. provided because of a failure in the network or in another
  1831. connection-oriented network component.
  1832. @xref
  1833. NdisCmActivateVc, NdisCmModifyCallQoSComplete, NdisCoSendPackets,
  1834. <f ProtocolCoCreateVc>
  1835. */
  1836. NDIS_STATUS ProtocolCmModifyCallQoS(
  1837. IN PBCHANNEL_OBJECT pBChannel, // @parm
  1838. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1839. // <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
  1840. // Specifies the handle to a call manager-allocated context area in which
  1841. // the call manager maintains its per-VC state. The call manager supplied
  1842. // this handle from its <f ProtocolCoCreateVc> function.
  1843. IN PCO_CALL_PARAMETERS pCallParameters // @parm
  1844. // Points to a CO_CALL_PARAMETERS structure that contains the new call
  1845. // parameters, as specified by a connection-oriented client, for the VC.
  1846. )
  1847. {
  1848. DBG_FUNC("ProtocolCmModifyCallQoS")
  1849. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1850. // Holds the result code returned by this function.
  1851. PMINIPORT_ADAPTER_OBJECT pAdapter;
  1852. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  1853. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1854. pAdapter = pBChannel->pAdapter;
  1855. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1856. DBG_ENTER(pAdapter);
  1857. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  1858. ("#%d VC=0x%X CallState=0x%X\n",
  1859. pBChannel->ObjectID,
  1860. pBChannel->NdisVcHandle, pBChannel->CallState
  1861. ));
  1862. // What do you want to do with this request?
  1863. DBG_ERROR(pAdapter, ("pCallParameters=0x%X\n", pCallParameters));
  1864. DBG_RETURN(pAdapter, Result);
  1865. return (Result);
  1866. }
  1867. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCoRequest
  1868. @func
  1869. <f ProtocolCoRequest> is a required function that handles OID_CO_XXX
  1870. requests initiated by calls to NdisCoRequest from the corresponding
  1871. client(s) or stand-alone call manager or initiated by an MCM driver's calls
  1872. to NdisMCmRequest.
  1873. @comm
  1874. Connection-oriented clients and stand-alone call managers communicate
  1875. information to each other by specifying an explicit NdisAfHandle when they
  1876. call NdisCoRequest. Similarly, a connection-oriented miniport with
  1877. integrated call-management support calls NdisMCmRequest with explicit
  1878. NdisAfHandles to communicate information to its individual clients. Such a
  1879. call to NdisCoRequest or NdisMCmRequest with an explicit NdisAfHandle causes
  1880. NDIS to call the ProtocolCoRequest function of the client, stand-alone call
  1881. manager, or MCM driver that shares the given NdisAfHandle.
  1882. If the input NdisVcHandle and NdisPartyHandle are NULL, ProtocolCoRequest
  1883. can consider the request global in nature. For example, ProtocolCoRequest
  1884. satisfies any OID_GEN_CO_XXX query for which it is passed only an explicit
  1885. NdisAfHandle by returning information about all currently active VCs,
  1886. including any active multipoint VCs, on the given address family.
  1887. An explicit NdisVcHandle or NdisPartyHandle indicates that ProtocolCoRequest
  1888. should satisfy the given request on a per-VC or per-party basis,
  1889. respectively.
  1890. ProtocolCoRequest can assume that the buffer at NdisRequest was allocated
  1891. from nonpaged pool and is, therefore, accessible at raised IRQL. The caller
  1892. of NdisCoRequest (or NdisMCmRequest) is responsible for releasing this
  1893. buffer and the internal buffer at InformationBuffer that it allocated when
  1894. its request has been completed.
  1895. If ProtocolCoRequest returns NDIS_STATUS_PENDING, the driver must make a
  1896. subsequent call to NdisCoRequestComplete or, for an MCM driver, to
  1897. NdisMCmRequestComplete when the driver completes its operations to satisfy
  1898. the given request.
  1899. For more information about the sets of OIDs defined for use with
  1900. NdisCoRequest, NdisMCmRequest, and NdisRequest, see Part 2 of this manual.
  1901. ProtocolCoRequest must be written so that it can run at IRQL DISPATCH_LEVEL.
  1902. @rdesc
  1903. ProtocolCoRequest can return one of the following:
  1904. @rvalue NDIS_STATUS_SUCCESS |
  1905. The client or call manager carried out the requested operation.
  1906. @rvalue NDIS_STATUS_PENDING |
  1907. The client or call manager is handling this request asynchronously, and it
  1908. will call NdisCoRequestComplete (or, from a NIC miniport with integrated
  1909. call-management support, NdisMCmRequestComplete) when the requested
  1910. operation is done.
  1911. @rvalue NDIS_STATUS_INVALID_LENGTH or NDIS_STATUS_BUFFER_TOO_SHORT |
  1912. The driver is failing this request because the caller of NdisCoRequest or
  1913. NdisMCmRequest did not supply an adequate InformationBuffer for the given
  1914. request. The driver set the BytesNeeded member in the buffer at NdisRequest
  1915. to the Oid-specific value of the InformationBufferLength required to carry
  1916. out the requested operation.
  1917. @rvalue NDIS_STATUS_XXX |
  1918. The client or call manager failed the request for some driver-determined
  1919. reason, such as invalid input data specified for a set.
  1920. @rvalue NDIS_STATUS_NOT_SUPPORTED |
  1921. The client or call manager failed this request because it did not recognize
  1922. the OID_GEN_CO_XXX code in the Oid member in the buffer at NdisRequest.
  1923. @xref
  1924. NdisClOpenAddressFamily, NdisCoRequest, NdisCoRequestComplete,
  1925. NdisMCmRequest, NdisMCmRequestComplete, NdisRequest, NDIS_REQUEST,
  1926. ProtocolCmOpenAf, ProtocolCoRequestComplete
  1927. */
  1928. NDIS_STATUS ProtocolCoRequest(
  1929. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  1930. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  1931. // <f AdapterCreate>. AKA ProtocolAfContext.<nl>
  1932. // Specifies the handle to the driver's per-AF context area. The client
  1933. // supplied this handle when it called NdisClOpenAddressFamily to connect
  1934. // itself to the call manager. The call manager supplied this handle from
  1935. // its <f ProtocolCmOpenAf> function, so this handle effectively identifies
  1936. // the particular client that issued this request.
  1937. IN PBCHANNEL_OBJECT pBChannel OPTIONAL, // @parm
  1938. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  1939. // <f BChannelCreate>. AKA ProtocolVcContext.<nl>
  1940. // Specifies the handle identifying the active VC for which the client or
  1941. // call manager is requesting or setting information if the request is
  1942. // VC-specific. Otherwise, this parameter is NULL.
  1943. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, // @parm
  1944. // Specifies the handle identifying the party on a multipoint VC for which
  1945. // the client or call manager is requesting or setting information if the
  1946. // request is party-specific. Otherwise, this parameter is NULL.
  1947. IN OUT PNDIS_REQUEST NdisRequest
  1948. // Points to a buffer, formatted as an NDIS_REQUEST structure specifying
  1949. // the operation to be carried out by ProtocolCoRequest. The Oid member of
  1950. // the NDIS_REQUEST structure contains the system-defined OID_GEN_CO_XXX
  1951. // code specifying the requested query or set operation, together with a
  1952. // buffer in which the protocol returns the requested information for a
  1953. // query or from which it transfers the given information for a set.
  1954. )
  1955. {
  1956. DBG_FUNC("ProtocolCmRequest")
  1957. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1958. // Holds the result code returned by this function.
  1959. // ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  1960. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  1961. DBG_ENTER(pAdapter);
  1962. Result = MiniportCoRequest(pAdapter, pBChannel, NdisRequest);
  1963. DBG_RETURN(pAdapter, Result);
  1964. return (Result);
  1965. }
  1966. /* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCoRequestComplete
  1967. @func
  1968. <f ProtocolCoRequestComplete> is a required function that postprocesses the
  1969. results of a connection-oriented client's or stand-alone call manager's call
  1970. to NdisCoRequest or of an MCM driver's call to NdisMCmRequest.
  1971. @comm
  1972. ProtocolCoRequestComplete can use the input Status as follows:
  1973. If this argument is NDIS_STATUS_SUCCESS, the BytesRead or BytesWritten
  1974. member of the NDIS_REQUEST structure has been set to specify how much data
  1975. was transferred into or from the buffer at InformationBuffer.
  1976. If the given OID_GEN_CO_XXX was a query, ProtocolCoRequestComplete can use
  1977. the data returned at InformationBuffer in any driver-determined way,
  1978. depending on the value of the Oid member.
  1979. ProtocolCoRequestComplete is responsible for releasing the driver-allocated
  1980. buffers at NdisRequest and InformationBuffer when the driver completes its
  1981. postprocessing of this request.
  1982. If this argument is NDIS_STATUS_INVALID_LENGTH or
  1983. NDIS_STATUS_BUFFER_TOO_SHORT, the BytesNeeded member specifies the
  1984. Oid-specific value of the InformationBufferLength required to carry out the
  1985. requested operation.
  1986. In these circumstances, ProtocolCoRequestComplete can allocate sufficient
  1987. buffer space for the request, set up another NDIS_REQUEST structure with the
  1988. required InformationBufferLength and the same Oid value, and retry the
  1989. driver's call to NdisCoRequest or NdisMCmRequest.
  1990. If this argument is an NDIS_STATUS_XXX that indicates an unrecoverable
  1991. error, ProtocolCoRequestComplete should release the buffer at NdisRequest
  1992. and carry out any driver-determined operations that are necessary. For
  1993. example, ProtocolCoRequestComplete might tear down the driver-created VC if
  1994. a returned error status indicates that the driver cannot continue to make
  1995. transfers on the virtual connection.
  1996. Even if a driver's call to NdisCoRequest or NdisMCmRequest returns something
  1997. other than NDIS_STATUS_PENDING, that driver should use its
  1998. ProtocolCoRequestComplete function to postprocess completed requests. Making
  1999. an internal call to the driver's own ProtocolCoRequestComplete function on
  2000. return from NdisCoRequest or NdisMCmRequest has almost no adverse effect on
  2001. the driver's performance, makes the driver's image smaller, and makes the
  2002. driver easier to maintain from one OS release to the next since such a
  2003. driver has no duplicate code doing status-return checking on
  2004. driver-initiated requests.
  2005. For more information about the sets of OIDs defined for use with
  2006. NdisCoRequest and NdisMCmRequest, see Part 2 of this manual.
  2007. ProtocolCoRequestComplete must be written so that it can run at IRQL
  2008. DISPATCH_LEVEL.
  2009. @xref
  2010. NdisCoRequest, NdisCoRequestComplete, NdisMCmRequest,
  2011. NdisMCmRequestComplete, NDIS_REQUEST, <f ProtocolCoRequest>
  2012. */
  2013. VOID ProtocolCoRequestComplete(
  2014. IN NDIS_STATUS Status, // @parm
  2015. // Specifies the final status of the driver-initiated request, either
  2016. // NDIS_STATUS_SUCCESS or a failure NDIS_STATUS_XXX that was set by the
  2017. // corresponding client or call manager that handled this request. This
  2018. // parameter is never NDIS_STATUS_PENDING.
  2019. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  2020. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  2021. // <f AdapterCreate>. AKA ProtocolAfContext.<nl>
  2022. // Specifies the handle to the driver's per-AF context area. The client
  2023. // supplied this handle when it called NdisClOpenAddressFamily to connect
  2024. // itself to the call manager. The call manager supplied this handle from
  2025. // its ProtocolCmOpenAf function, so this handle effectively identifies the
  2026. // particular client to which this request was directed.
  2027. IN PBCHANNEL_OBJECT pBChannel OPTIONAL, // @parm
  2028. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  2029. // <f BChannelCreate>. AKA ProtocolVcContext.<nl>
  2030. // Specifies the handle identifying the active VC for which the client or
  2031. // call manager was requesting or setting information if the request was
  2032. // VC-specific. Otherwise, this parameter is NULL.
  2033. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, // @parm
  2034. // Specifies the handle identifying the party on a multipoint VC for which
  2035. // the client or call manager was requesting or setting information if the
  2036. // request is party-specific. Otherwise, this parameter is NULL.
  2037. IN PNDIS_REQUEST NdisRequest // @parm
  2038. // Points to the driver-allocated buffer, formatted as an NDIS_REQUEST
  2039. // structure that the driver passed in a preceding call to NdisCoRequest or
  2040. // NdisMCmRequest. The Oid member of the NDIS_REQUEST structure contains
  2041. // the system-defined OID_GEN_CO_XXX code specifying the requested query or
  2042. // set operation, together with a buffer in which the corresponding client
  2043. // or call manager returned the requested information for a query or from
  2044. // which it transferred the given information for a set if Status is
  2045. // NDIS_STATUS_SUCCESS.
  2046. )
  2047. {
  2048. DBG_FUNC("ProtocolCmRequestComplete")
  2049. // ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  2050. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  2051. DBG_ENTER(pAdapter);
  2052. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  2053. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  2054. pBChannel->ObjectID,
  2055. pBChannel->NdisVcHandle, pBChannel->CallState, Status
  2056. ));
  2057. // MCM's don't typically need this, since there's nothing below...
  2058. DBG_LEAVE(pAdapter);
  2059. }
  2060. /* @doc INTERNAL CallMgr CallMgr_c AllocateIncomingCallParameters
  2061. @func
  2062. <f AllocateIncomingCallParameters> is called by <f SetupIncomingCall>
  2063. when getting ready to indicate an incoming call up to NDPROXY.
  2064. @comm
  2065. AllocateIncomingCallParameters allocates memory for the incoming call
  2066. parameters <t PCO_CALL_PARAMETERS>. The memory is only allocated the
  2067. first time a call comes in on a particular BChannel. After that, the
  2068. same structure is reused for each incoming call on that BChannel.
  2069. The structure is defined by NDPROXY, CONDIS, and TAPI so it includes
  2070. all the necessary media specific parameters. The data structures are
  2071. allocated and laid out end to end in the following format:
  2072. <tab> sizeof(CO_CALL_PARAMETERS)<nl>
  2073. <tab> sizeof(CO_CALL_MANAGER_PARAMETERS)<nl>
  2074. <tab> sizeof(CO_MEDIA_PARAMETERS)<nl>
  2075. <tab> sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)<nl>
  2076. <tab> sizeof(LINE_CALL_INFO)<nl>
  2077. The call parameters for the sample driver are hard coded, but you should
  2078. fill in the correct information from incoming call request.
  2079. */
  2080. PCO_CALL_PARAMETERS AllocateIncomingCallParameters(
  2081. IN PBCHANNEL_OBJECT pBChannel // @parm
  2082. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  2083. // <f ProtocolCoCreateVc>.
  2084. )
  2085. {
  2086. DBG_FUNC("AllocateIncomingCallParameters")
  2087. PCO_CALL_PARAMETERS pCp;
  2088. PCO_CALL_MANAGER_PARAMETERS pCmp;
  2089. PCO_MEDIA_PARAMETERS pMp;
  2090. PCO_AF_TAPI_INCOMING_CALL_PARAMETERS pTcp;
  2091. PLINE_CALL_INFO pLci;
  2092. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  2093. // Holds the result code returned by this function.
  2094. PMINIPORT_ADAPTER_OBJECT pAdapter;
  2095. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  2096. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  2097. pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
  2098. DBG_ENTER(pAdapter);
  2099. ASSERT(pBChannel->NdisTapiSap.ulMediaModes & LINEMEDIAMODE_DIGITALDATA);
  2100. pBChannel->MediaMode = LINEMEDIAMODE_DIGITALDATA;
  2101. pBChannel->BearerMode = LINEBEARERMODE_DATA;
  2102. pBChannel->LinkSpeed = _64KBPS;
  2103. if (pBChannel->pInCallParms != NULL)
  2104. {
  2105. // Already allocated call parameters for this channel.
  2106. return (pBChannel->pInCallParms);
  2107. }
  2108. pBChannel->CallParmsSize = sizeof(CO_CALL_PARAMETERS)
  2109. + sizeof(CO_CALL_MANAGER_PARAMETERS)
  2110. + sizeof(CO_MEDIA_PARAMETERS)
  2111. + sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)
  2112. + sizeof(LINE_CALL_INFO);
  2113. ALLOCATE_MEMORY(pBChannel->pInCallParms,
  2114. pBChannel->CallParmsSize,
  2115. pAdapter->MiniportAdapterHandle);
  2116. if (pBChannel->pInCallParms == NULL)
  2117. {
  2118. return (pBChannel->pInCallParms);
  2119. }
  2120. NdisZeroMemory(pBChannel->pInCallParms, pBChannel->CallParmsSize);
  2121. DBG_NOTICE(pAdapter,(
  2122. "\n"
  2123. "\t\tsizeof(CO_CALL_PARAMETERS) =%03d\n"
  2124. "\t\tsizeof(CO_CALL_MANAGER_PARAMETERS) =%03d\n"
  2125. "\t\tsizeof(CO_MEDIA_PARAMETERS) =%03d\n"
  2126. "\t\tsizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)=%03d\n"
  2127. "\t\tsizeof(LINE_CALL_INFO) =%03d\n"
  2128. "\t\tTotal =%03d\n",
  2129. sizeof(CO_CALL_PARAMETERS),
  2130. sizeof(CO_CALL_MANAGER_PARAMETERS),
  2131. sizeof(CO_MEDIA_PARAMETERS),
  2132. sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS),
  2133. sizeof(LINE_CALL_INFO),
  2134. pBChannel->CallParmsSize
  2135. ));
  2136. pCp = (PCO_CALL_PARAMETERS) pBChannel->pInCallParms;
  2137. pCmp = (PCO_CALL_MANAGER_PARAMETERS)(pCp + 1);
  2138. pMp = (PCO_MEDIA_PARAMETERS) (pCmp + 1);
  2139. pTcp = (PCO_AF_TAPI_INCOMING_CALL_PARAMETERS)
  2140. pMp->MediaSpecific.Parameters;
  2141. pLci = (PLINE_CALL_INFO) (pTcp + 1);
  2142. // TODO: Fill in the call parameters as needed.
  2143. pCp->Flags = PERMANENT_VC;
  2144. pCp->CallMgrParameters = pCmp;
  2145. pCp->MediaParameters = pMp;
  2146. pCmp->Transmit.TokenRate = pBChannel->LinkSpeed / 8;
  2147. pCmp->Transmit.TokenBucketSize = pAdapter->pCard->BufferSize;
  2148. pCmp->Transmit.PeakBandwidth = pBChannel->LinkSpeed / 8;
  2149. pCmp->Transmit.Latency = 0;
  2150. pCmp->Transmit.DelayVariation = 0;
  2151. pCmp->Transmit.ServiceType = SERVICETYPE_BESTEFFORT;
  2152. pCmp->Transmit.MaxSduSize = pAdapter->pCard->BufferSize;
  2153. pCmp->Transmit.MinimumPolicedSize = 0;
  2154. pCmp->Receive = pCmp->Transmit;
  2155. pCmp->CallMgrSpecific.ParamType = 0;
  2156. pCmp->CallMgrSpecific.Length = 0;
  2157. pMp->Flags = TRANSMIT_VC | RECEIVE_VC;
  2158. pMp->ReceiveSizeHint = pAdapter->pCard->BufferSize;
  2159. pMp->MediaSpecific.ParamType = 0;
  2160. pMp->MediaSpecific.Length = sizeof(*pTcp) + sizeof(*pLci);
  2161. pTcp->ulLineID = pBChannel->NdisTapiSap.ulLineID;
  2162. pTcp->ulAddressID = TSPI_ADDRESS_ID;
  2163. pTcp->ulFlags = CO_TAPI_FLAG_INCOMING_CALL;
  2164. pTcp->LineCallInfo.Length = sizeof(*pLci);
  2165. pTcp->LineCallInfo.MaximumLength = sizeof(*pLci);
  2166. pTcp->LineCallInfo.Offset = sizeof(NDIS_VAR_DATA_DESC);
  2167. pLci->ulTotalSize =
  2168. pLci->ulNeededSize =
  2169. pLci->ulUsedSize = sizeof(*pLci);
  2170. /*
  2171. // The link has all the call information we need to return.
  2172. */
  2173. pLci->hLine = (ULONG) (ULONG_PTR) pBChannel;
  2174. pLci->ulLineDeviceID = pTcp->ulLineID;
  2175. pLci->ulAddressID = pTcp->ulAddressID;
  2176. pLci->ulBearerMode = pBChannel->BearerMode;
  2177. pLci->ulRate = pBChannel->LinkSpeed;
  2178. pLci->ulMediaMode = pBChannel->MediaMode;
  2179. pLci->ulCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  2180. pLci->ulCallStates = pBChannel->CallStatesCaps;
  2181. /*
  2182. // We don't support any of the callerid functions.
  2183. */
  2184. pLci->ulCallerIDFlags =
  2185. pLci->ulCalledIDFlags =
  2186. pLci->ulConnectedIDFlags =
  2187. pLci->ulRedirectionIDFlags =
  2188. pLci->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  2189. DBG_RETURN(pAdapter, pBChannel->pInCallParms);
  2190. return (pBChannel->pInCallParms);
  2191. }
  2192. /* @doc INTERNAL CallMgr CallMgr_c SetupIncomingCall
  2193. @func
  2194. <f SetupIncomingCall> is called by the card level DPC routine when it
  2195. detects an incoming call from the network.
  2196. @comm
  2197. Before calling this routine, the caller should save information about
  2198. the call so it can be used by <f AllocateIncomingCallParameters> to
  2199. setup the incoming call parameters for NDPROXY.
  2200. @rdesc
  2201. <f SetupIncomingCall> returns zero if it is successful.<nl>
  2202. Otherwise, a non-zero return value indicates an error condition.
  2203. */
  2204. NDIS_STATUS SetupIncomingCall(
  2205. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  2206. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  2207. // <f AdapterCreate>.
  2208. OUT PBCHANNEL_OBJECT * ppBChannel // @parm
  2209. // Specifies, on output, a pointer to the <t BCHANNEL_OBJECT> instance
  2210. // returned by <f ProtocolCoCreateVc> that is to be associated with this
  2211. // incoming call.
  2212. )
  2213. {
  2214. DBG_FUNC("SetupIncomingCall")
  2215. NDIS_STATUS Result;
  2216. // Holds the result code returned by this function.
  2217. PCO_CALL_PARAMETERS pCallParams;
  2218. // Pointer to the incoming call parameters.
  2219. PBCHANNEL_OBJECT pBChannel;
  2220. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  2221. DBG_ENTER(pAdapter);
  2222. // See if there's a VC availble for this call.
  2223. Result = ProtocolCoCreateVc(pAdapter, NULL, ppBChannel);
  2224. if (Result != NDIS_STATUS_SUCCESS)
  2225. {
  2226. goto exit;
  2227. }
  2228. // Save the VC info and allocate the call parameters.
  2229. pBChannel = *ppBChannel;
  2230. pBChannel->Flags |= VCF_INCOMING_CALL;
  2231. pCallParams = AllocateIncomingCallParameters(pBChannel);
  2232. // Make sure we have the parameters
  2233. if (pCallParams == NULL)
  2234. {
  2235. Result = NDIS_STATUS_RESOURCES;
  2236. goto error2;
  2237. }
  2238. // Tell NDPROXY to create a VC for this call.
  2239. Result = NdisMCmCreateVc(pAdapter->MiniportAdapterHandle,
  2240. pAdapter->NdisAfHandle,
  2241. pBChannel,
  2242. &pBChannel->NdisVcHandle);
  2243. if (Result != NDIS_STATUS_SUCCESS)
  2244. {
  2245. DBG_ERROR(pAdapter, ("NdisMCmCreateVc Status=0x%X\n", Result));
  2246. goto error2;
  2247. }
  2248. // Tell NDPROXY to activate the VC.
  2249. Result = NdisMCmActivateVc(pBChannel->NdisVcHandle, pCallParams);
  2250. if (Result != NDIS_STATUS_SUCCESS)
  2251. {
  2252. DBG_ERROR(pAdapter, ("NdisMCmActivateVc Status=0x%X\n", Result));
  2253. goto error3;
  2254. }
  2255. // Mark the VC as active and update the call state.
  2256. pBChannel->Flags |= VCF_VC_ACTIVE;
  2257. pBChannel->CallState = LINECALLSTATE_OFFERING;
  2258. DBG_FILTER(pAdapter,DBG_TAPICALL_ON,
  2259. ("#%d VC=0x%X AF=0x%X SAP=0x%X\n",
  2260. pBChannel->ObjectID,
  2261. pBChannel->NdisVcHandle,
  2262. pAdapter->NdisAfHandle, pBChannel->NdisSapHandle
  2263. ));
  2264. // Need to use the NDIS SAP handle
  2265. if(!ReferenceSap(pAdapter, pBChannel))
  2266. {
  2267. NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
  2268. goto error3;
  2269. }
  2270. // Tell NDPROXY to dispatch the call to the TAPI clients.
  2271. Result = NdisMCmDispatchIncomingCall(pBChannel->NdisSapHandle,
  2272. pBChannel->NdisVcHandle,
  2273. pCallParams);
  2274. switch (Result)
  2275. {
  2276. case NDIS_STATUS_SUCCESS:
  2277. DBG_NOTICE(pAdapter,("NdisMCmDispatchIncomingCall completed synchronously\n"));
  2278. ProtocolCmIncomingCallComplete(Result, pBChannel, NULL);
  2279. goto exit;
  2280. case NDIS_STATUS_PENDING:
  2281. DBG_NOTICE(pAdapter,("NdisMCmDispatchIncomingCall returned pending\n"));
  2282. // Let ProtocolCmIncomingCallComplete deal with it now.
  2283. goto exit;
  2284. }
  2285. // Done with the NDIS SAP handle
  2286. DereferenceSap(pAdapter, pBChannel);
  2287. // BUMMER - There must be a problem with NDPRROXY...
  2288. DBG_ERROR(pAdapter, ("NdisMCmDispatchIncomingCall Status=0x%X\n", Result));
  2289. pBChannel->CallState = LINECALLSTATE_IDLE;
  2290. if (pBChannel->Flags & VCF_VC_ACTIVE)
  2291. {
  2292. pBChannel->Flags &= ~VCF_VC_ACTIVE;
  2293. NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
  2294. }
  2295. error3:
  2296. if (pBChannel->NdisVcHandle)
  2297. {
  2298. NdisMCmDeleteVc(pBChannel->NdisVcHandle);
  2299. pBChannel->NdisVcHandle = NULL;
  2300. }
  2301. error2:
  2302. ProtocolCoDeleteVc((NDIS_HANDLE) pBChannel);
  2303. exit:
  2304. DBG_RETURN(pAdapter, Result);
  2305. return (Result);
  2306. }
  2307. /* @doc INTERNAL CallMgr CallMgr_c InitiateCallTeardown
  2308. @func
  2309. <f InitiateCallTeardown> is called by the card level DPC routine when it
  2310. detects a call disconnect from the network.
  2311. @comm
  2312. The disconnect here is coming from the telephone network rather than from
  2313. NDIS. This can be called on either an incoming call or an outgoing call
  2314. when the miniport has determined that the link has been lost to the remote
  2315. endpoint.
  2316. */
  2317. VOID InitiateCallTeardown(
  2318. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  2319. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  2320. // <f AdapterCreate>.
  2321. IN PBCHANNEL_OBJECT pBChannel // @parm
  2322. // A pointer to the <t BCHANNEL_OBJECT> instance returned by
  2323. // <f ProtocolCoCreateVc>.
  2324. )
  2325. {
  2326. DBG_FUNC("InitiateCallTeardown")
  2327. NDIS_STATUS Status;
  2328. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  2329. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  2330. DBG_ENTER(pAdapter);
  2331. if (pBChannel->Flags & VCF_VC_ACTIVE)
  2332. {
  2333. // Normal teardown.
  2334. Status = NDIS_STATUS_SUCCESS;
  2335. }
  2336. else
  2337. {
  2338. // Call never fully established.
  2339. Status = NDIS_STATUS_FAILURE;
  2340. }
  2341. DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
  2342. ("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
  2343. pBChannel->ObjectID,
  2344. pBChannel->NdisVcHandle, pBChannel->CallState,
  2345. Status
  2346. ));
  2347. pBChannel->CallState = LINECALLSTATE_DISCONNECTED;
  2348. // Make sure there are no packets left on this channel before it closes.
  2349. FlushSendPackets(pAdapter, pBChannel);
  2350. // Notify NDPROXY that the call's connection has been lost.
  2351. NdisMCmDispatchIncomingCloseCall(Status,
  2352. pBChannel->NdisVcHandle,
  2353. NULL, 0);
  2354. DBG_LEAVE(pAdapter);
  2355. }