Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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