mirror of https://github.com/tongzx/nt5src
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
3053 lines
119 KiB
/*
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
(C) Copyright 1999
|
|
All rights reserved.
|
|
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
Portions of this software are:
|
|
|
|
(C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
|
|
License to use this software is granted under the same terms
|
|
outlined in the Microsoft Windows Device Driver Development Kit.
|
|
|
|
(C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
|
|
License to use this software is granted under the terms outlined in
|
|
the Microsoft Windows Device Driver Development Kit.
|
|
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@doc INTERNAL CallMgr CallMgr_c
|
|
|
|
@module CallMgr.c |
|
|
|
|
This module defines the interface to the <t CALL_MANAGER_OBJECT>.
|
|
Supports the interface between NDISPROXY and the Miniport. All the
|
|
Address Family, SAP, VC, and call related events pass through these
|
|
interface on their way to and from NDPROXY.
|
|
|
|
@comm
|
|
|
|
This module will require some changes depending on how your hardware
|
|
works. But in general, you should try to isolate your changes down in
|
|
<f DChannel\.c> and <f Card\.c>.
|
|
|
|
@head3 Contents |
|
|
@index class,mfunc,func,msg,mdata,struct,enum | CallMgr_c
|
|
|
|
@end
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
*/
|
|
|
|
/* @doc EXTERNAL INTERNAL
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@topic 3.1 Call Manager Interface |
|
|
|
|
The NDPROXY driver is a provider for the Windows Telephony service.
|
|
Applications make TAPI requests and the Windows Telephony service routes
|
|
these requests to NDPROXY. NDPROXY implements the Telephony Service Provider
|
|
Interface (TSPI) for the Windows Telephony service. NDPROXY then
|
|
communicates through NDIS with the NDISWAN driver and CoNDIS WAN miniport
|
|
drivers. These CoNDIS WAN miniport drivers must provide TAPI capability.
|
|
|
|
The NDPROXY driver passes TAPI requests by encapsulating TAPI parameters in
|
|
NDIS structures. NDPROXY presents a client interface to CoNDIS WAN miniport
|
|
drivers and a call manager interface to NDISWAN. NDISWAN presents a client
|
|
interface to NDPROXY. CoNDIS WAN miniport drivers present a call manager
|
|
interface to NDPROXY and a CoNDIS miniport interface to NDISWAN.
|
|
|
|
A TAPI-capable CoNDIS WAN miniport driver registers and initializes itself
|
|
as a user of both WAN and TAPI services. After registration and
|
|
initialization are complete, a user-level application can make telephonic
|
|
requests to the Windows Telephony service module, which converts TAPI
|
|
requests to TSPI requests. The Windows Telephony service module passes these
|
|
requests to the NDPROXY driver. NDPROXY encapsulates parameters for TAPI
|
|
requests in NDIS structures and routes the requests to the appropriate
|
|
CoNDIS WAN miniport driver. These requests are routed in order to set up,
|
|
monitor, and tear down lines, and calls.
|
|
|
|
A TAPI-capable CoNDIS WAN miniport driver can also communicate changes in
|
|
the states of lines and calls, for instance the arrival of an incoming call
|
|
or a remote disconnection.
|
|
|
|
@ex Registering and opening the TAPI address family between NDPROXY and MCM |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| | NdisMCmRegisterAddressFamily |
|
|
| ProtocolCoAfRegisterNotify |«---------------------------------|
|
|
|«---------------------------------| |
|
|
| NdisClOpenAddressFamily | |
|
|
|---------------------------------»| ProtocolCmOpenAf |
|
|
| |---------------------------------»|
|
|
| | CompleteCmOpenAf |
|
|
| | NdisCmOpenAddressFamilyComplete |
|
|
| ProtocolOpenAfComplete |«---------------------------------|
|
|
|«---------------------------------| |
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex Closing the TAPI address family between NDPROXY and MCM |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| NdisClCloseAddressFamily | |
|
|
|---------------------------------»| ProtocolCmCloseAf |
|
|
| |---------------------------------»|
|
|
| | CompleteCmCloseAf |
|
|
| | NdisMCmCloseAddressFamilyComplete|
|
|
| ProtocolClCloseAfComplete |«---------------------------------|
|
|
|«---------------------------------| |
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex Registering a SAP between NDPROXY and MCM |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| NdisClRegisterSap | |
|
|
|---------------------------------»| ProtocolCmRegisterSap |
|
|
| |---------------------------------»|
|
|
| | CompleteCmRegisterSap |
|
|
| | NdisMCmRegisterSapComplete |
|
|
| ProtocolClRegisterSapComplete |«---------------------------------|
|
|
|«---------------------------------| |
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex Deregistering a SAP between NDPROXY and MCM |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| NdisClDeregisterSap | |
|
|
|---------------------------------»| ProtocolCmDeregisterSap |
|
|
| |---------------------------------»|
|
|
| | CompleteCmDeregisterSap |
|
|
| | NdisMCmDeregisterSapComplete |
|
|
| ProtocolClDeregisterSapComplete |«---------------------------------|
|
|
|«---------------------------------| |
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex Seting up an outgoing call from NDPROXY to MCM |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| NdisCoCreateVc | ProtocolCoCreateVC |
|
|
|---------------------------------»|«--------------------------------»|
|
|
| NdisClMakeCall | ProtocolCmMakeCall |
|
|
|---------------------------------»|---------------------------------»|
|
|
| . | . |
|
|
| . | . |
|
|
| . | . |
|
|
| | NdisMCmActivateVC |
|
|
| |«---------------------------------|
|
|
| | ProtocolCmActivateVcComplete |
|
|
| |---------------------------------»|
|
|
| ProtocolClMakeCallComplete | NdisMCmMakeCallComplete |
|
|
|«--------------------------------»|«---------------------------------|
|
|
| . | . |
|
|
| . "Tranmit & receive packets" . |
|
|
| . | . |
|
|
| "Client/MCM initiated call termination" |
|
|
| NdisCoDeleteVc | ProtocolCoDeleteVc |
|
|
|---------------------------------»|«--------------------------------»|
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex Setting up an incoming call from MCM to NDPROXY |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| NdisCoCreateVc | NdisMCmCreateVC |
|
|
|«--------------------------------»|«---------------------------------|
|
|
| | NdisMCmActivateVC |
|
|
| |«---------------------------------|
|
|
| | ProtocolCmActivateVcComplete |
|
|
| |---------------------------------»|
|
|
| ProtocolClIncomingCall | NdisMCmDispatchIncomingCall |
|
|
|«---------------------------------|«---------------------------------|
|
|
| | |
|
|
| NdisClIncomingCallComplete | ProtocolCmIncomingCallComplete |
|
|
|---------------------------------»|«--------------------------------»|
|
|
| ProtocolClCallConnected | NdisMCmDispatchCallConnected |
|
|
|«--------------------------------»|«---------------------------------|
|
|
| . | . |
|
|
| . "Tranmit & receive packets" . |
|
|
| . | . |
|
|
| "Client/MCM initiated call termination" |
|
|
| ProtocolCoDeleteVc | NdisMCmDeleteVc |
|
|
|«--------------------------------»|«---------------------------------|
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex NDPROXY initiated call termination |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| NdisClCloseCall | ProtocolCmCloseCall |
|
|
|---------------------------------»|---------------------------------»|
|
|
| | NdisMCmDeactivateVc |
|
|
| |«---------------------------------|
|
|
| | ProtocolCmDeactivateVcComplete |
|
|
| |---------------------------------»|
|
|
| ProtocolClCloseCallComplete | NdisCmCloseCallComplete |
|
|
|«--------------------------------»|«---------------------------------|
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@ex MCM initiated call termination |
|
|
|
|
NDPROXY NDIS MCM
|
|
|----------------------------------|----------------------------------|
|
|
| ProtocolClIncomingCloseCall | NdisMCmDispatchIncomingCloseCall |
|
|
|«---------------------------------|«---------------------------------|
|
|
| NdisClCloseCall | ProtocolCmCloseCall |
|
|
|---------------------------------»|---------------------------------»|
|
|
| | NdisMCmDeactivateVc |
|
|
| |«---------------------------------|
|
|
| | ProtocolCmDeactivateVcComplete |
|
|
| |---------------------------------»|
|
|
| ProtocolClCloseCallComplete | NdisCmCloseCallComplete |
|
|
|«--------------------------------»|«---------------------------------|
|
|
|----------------------------------|----------------------------------|
|
|
|
|
@end
|
|
*/
|
|
|
|
#define __FILEID__ CALL_MANAGER_OBJECT_TYPE
|
|
// Unique file ID for error logging
|
|
|
|
#include "Miniport.h" // Defines all the miniport objects
|
|
|
|
#if defined(NDIS_LCODE)
|
|
# pragma NDIS_LCODE // Windows 9x wants this code locked down!
|
|
# pragma NDIS_LDATA
|
|
#endif
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c CompleteCmOpenAf
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f CompleteCmOpenAf> is called when the miniport is done processing the
|
|
<f ProtocolCmOpenAf> request.
|
|
|
|
@comm
|
|
|
|
If you return NDIS_STATUS_PENDING from <f ProtocolCmOpenAf>, you must
|
|
call <f CompleteCmOpenAf> so that <f NdisMCmOpenAddressFamilyComplete>
|
|
can be called to complete the request.
|
|
|
|
*/
|
|
|
|
VOID CompleteCmOpenAf(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>.
|
|
|
|
IN NDIS_STATUS Status // @parm
|
|
// The NDIS status code to be passed to NdisMCmOpenAddressFamilyComplete.
|
|
)
|
|
{
|
|
DBG_FUNC("CompleteCmOpenAf")
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
/*
|
|
// Try to connect to the DChannel.
|
|
*/
|
|
DChannelOpen(pAdapter->pDChannel);
|
|
|
|
NdisMCmOpenAddressFamilyComplete(Status, pAdapter->NdisAfHandle, pAdapter);
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmOpenAf
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmOpenAf> is a required function that allocates per-open
|
|
resources for a call manager to interact with a connection-oriented NDIS
|
|
client that is opening the address family.
|
|
|
|
@comm
|
|
|
|
ProtocolCmOpenAf performs any required allocations of dynamic resources
|
|
and structures that the call manager writer deems necessary to perform
|
|
operations on behalf of the client that is opening an instance of this
|
|
address family. Such resources include, but are not limited to, memory
|
|
buffers, data structures, events, and other such similar resources. A call
|
|
manager should also initialize any relevant per-open data before returning
|
|
control to NDIS.
|
|
|
|
When a call manager has allocated its per-open state area, the address of
|
|
the state area should be set in the CallMgrAfContext handle before returning
|
|
control to NDIS. To do this, dereference CallMgrAfContext and store a
|
|
pointer to the data area as the value of the handle. For example:
|
|
|
|
*CallMgrAfContext = SomeBuffer; // We use <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
If ProtocolCmOpenAf cannot allocate the per-open resources it needs to
|
|
carry out subsequent requests on behalf of the client opening this address
|
|
family, it should free all resources that it allocated for the open and
|
|
return control to the NDIS with NDIS_STATUS_RESOURCES.
|
|
|
|
If ProtocolCmOpenAf has completed its required operations and the CM is
|
|
ready to accept requests from the client, ProtocolCmOpenAf should return
|
|
control as quickly as possible with a status of NDIS_STATUS_SUCCESS.
|
|
|
|
ProtocolCmOpenAf must be written so that it can run at IRQL DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCmOpenAf returns the status of its operation(s) as one of the
|
|
following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager has successfully allocated and initialized
|
|
any resources necessary to accept requests from the client to this address
|
|
family.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the requested operation is being handled asynchronously. The
|
|
call manager must call NdisCmOpenAddressFamilyComplete when it has completed
|
|
all its open-AF operations to indicate to NDIS (and the client) that the
|
|
operation(s) has been completed.
|
|
|
|
@rvalue NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the call manager could not complete its necessary
|
|
operation(s) because of a lack of available system resources, such as
|
|
memory.
|
|
|
|
@rvalue NDIS_STATUS_XXX |
|
|
|
|
Indicates that the call manager could not set itself into a state where it
|
|
can accept requests from the client to operate on this address family. This
|
|
could be an error status propagated from another NDIS library function or
|
|
any error status determined appropriate by the driver writer.
|
|
|
|
@xref
|
|
|
|
NdisClOpenAddressFamily, NdisCmOpenAddressFamilyComplete,
|
|
NdisCmRegisterAddressFamily, NdisOpenAdapter, <f ProtocolCmCloseAf>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmOpenAf(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>. AKA CallMgrBindingContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call managers maintains its per-binding state information. The call
|
|
// manager supplied this handle when it called NdisOpenAdapter.
|
|
|
|
IN PCO_ADDRESS_FAMILY AddressFamily, // @parm
|
|
// Specifies the address family that a client is opening. This address
|
|
// family was registered by the call manager when it called
|
|
// NdisCmRegisterAddressFamily.
|
|
|
|
IN NDIS_HANDLE NdisAfHandle, // @parm
|
|
// Specifies a handle, supplied by NDIS, that uniquely identifies this
|
|
// address family instance. This handle is opaque to the call manager and
|
|
// reserved for system use.
|
|
|
|
OUT PNDIS_HANDLE CallMgrAfContext // @parm
|
|
// Specifies the handle to a call manager-supplied context area in which
|
|
// the call manager maintains state about this open of an address family it
|
|
// provides.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmOpenAf")
|
|
|
|
NDIS_STATUS Status;
|
|
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
if (pAdapter->NdisAfHandle != NULL)
|
|
{
|
|
// Our AF has already been opened and it doesn't make any sense to
|
|
// accept another since there is no way to distinguish which should
|
|
// receive incoming calls.
|
|
DBG_ERROR(pAdapter, ("Attempting to open AF again!\n"));
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
pAdapter->NdisAfHandle = NdisAfHandle;
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("TAPI AF=0x%X AddressFamily=0x%X MajorVersion=0x%X MinorVersion=0x%X\n",
|
|
NdisAfHandle,
|
|
AddressFamily->AddressFamily,
|
|
AddressFamily->MajorVersion,
|
|
AddressFamily->MinorVersion
|
|
));
|
|
|
|
// Since we return NDIS_STATUS_PENDING here, we must call
|
|
// NdisMCmOpenAddressFamilyComplete to complete this request.
|
|
// If necessary, you can do the completion asynchronously.
|
|
*CallMgrAfContext = pAdapter;
|
|
CompleteCmOpenAf(pAdapter, NDIS_STATUS_SUCCESS);
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
DBG_RETURN(pAdapter, Status);
|
|
return (Status);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c CompleteCmCloseAf
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f CompleteCmCloseAf> is called when the miniport is done processing the
|
|
<f ProtocolCmCloseAf> request.
|
|
|
|
@comm
|
|
|
|
If you return NDIS_STATUS_PENDING from <f ProtocolCmCloseAf>, you must
|
|
call <f CompleteCmCloseAf> so that <f NdisMCmCloseAddressFamilyComplete>
|
|
can be called to complete the request.
|
|
*/
|
|
|
|
VOID CompleteCmCloseAf(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>.
|
|
|
|
IN NDIS_STATUS Status // @parm
|
|
// The NDIS status code to be passed to NdisMCmCloseAddressFamilyComplete.
|
|
)
|
|
{
|
|
DBG_FUNC("CompleteCmCloseAf")
|
|
|
|
NDIS_HANDLE NdisAfHandle;
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
NdisAfHandle = pAdapter->NdisAfHandle;
|
|
pAdapter->NdisAfHandle = NULL;
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("TAPI AF=0x%X\n",
|
|
NdisAfHandle));
|
|
|
|
NdisMCmCloseAddressFamilyComplete(Status, NdisAfHandle);
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmCloseAf
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmCloseAf> is a required function that releases per-open
|
|
resources for an address family that a call manager supports.
|
|
|
|
@comm
|
|
|
|
ProtocolCmCloseAf releases and/or deactivates any resources that were
|
|
allocated by the call manager in its ProtocolCmOpenAf function. The call
|
|
manager also should undo any other actions it took on behalf of the
|
|
connection-oriented client when the address family was opened by that
|
|
client.
|
|
|
|
If there are any outstanding requests or connections still open on an
|
|
address family stored in the CallMgrAfContext, a call manager can respond to
|
|
a client's request to close the address family in either of the following
|
|
ways:
|
|
|
|
The call manager can fail the request with NDIS_STATUS_NOT_ACCEPTED.
|
|
|
|
The call manager can return NDIS_STATUS_PENDING. After the client has closed
|
|
all calls and deregistered all SAPs, the call manager can then close the
|
|
address family and call Ndis(M)CmCloseAddressFamilyComplete to notify the
|
|
client. This is the preferred response.
|
|
|
|
ProtocolCmCloseAf must be written so that it can run at IRQL DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCmCloseAf returns the status of its operation(s) as one of the
|
|
following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager has successfully released or deactivated any
|
|
resources that is allocated on behalf of the connection-oriented client that
|
|
opened this instance of the address family.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the request to close the open instance of the address family
|
|
will be completed asynchronously. The call manager must call
|
|
NdisCmCloseAddressFamilyComplete when all such operations have been
|
|
completed.
|
|
|
|
@xref
|
|
|
|
NdisCmCloseAddressFamilyComplete, <f ProtocolCmOpenAf>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmCloseAf(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f ProtocolCmOpenAf>. AKA CallMgrAfContext.<nl>
|
|
// Specifies the handle to the call manager's per-AF context area,
|
|
// originally supplied to NDIS by the call manager's ProtocolCmOpenAf
|
|
// function.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmCloseAf")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// Since we return NDIS_STATUS_PENDING here, we must call
|
|
// NdisMCmCloseAddressFamilyComplete to complete this request.
|
|
// TODO: If necessary, you can do the completion asynchronously.
|
|
DChannelClose(pAdapter->pDChannel);
|
|
CompleteCmCloseAf(pAdapter, NDIS_STATUS_SUCCESS);
|
|
Result = NDIS_STATUS_PENDING;
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
VOID CompleteCmRegisterSap(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
|
|
|
|
IN NDIS_STATUS Status // @parm
|
|
// The NDIS status code to be passed to NdisMCmRegisterSapComplete.
|
|
)
|
|
{
|
|
DBG_FUNC("CompleteCmRegisterSap")
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
/*
|
|
// TODO: What statistics do you want to collect and report?
|
|
*/
|
|
pAdapter->TotalRxBytes = 0;
|
|
pAdapter->TotalTxBytes = 0;
|
|
pAdapter->TotalRxPackets = 0;
|
|
pAdapter->TotalTxPackets = 0;
|
|
|
|
// If you return NDIS_STATUS_PENDING from ProtocolCmRegisterSap, you
|
|
// must call NdisMCmRegisterSapComplete to complete the request.
|
|
NdisMCmRegisterSapComplete(Status, pBChannel->NdisSapHandle, pBChannel);
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmRegisterSap
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmRegisterSap> is a required function that is called by NDIS to
|
|
request that a call manager register a SAP (service access point) on behalf
|
|
of a connection-oriented client.
|
|
|
|
@comm
|
|
|
|
ProtocolCmRegisterSap communicates with network control devices or other
|
|
media-specific agents, as necessary, to register the SAP, as specified at
|
|
Sap, on the network for a connection-oriented client. Such actions could
|
|
include, but are not limited to communicating with switching hardware,
|
|
communicating with a network control station, or other actions that are
|
|
appropriate to the network medium.
|
|
|
|
If a call manager is required to communicate with networking control agents
|
|
(e.g. a network switch) it should use a virtual connection to the network
|
|
control agent that it established in its ProtocolBindAdapter function.
|
|
Standalone call managers communicate through the underlying NIC miniport by
|
|
calling NdisCoSendPackets. NIC miniports with integrated call-management
|
|
support never call NdisCoSendPackets. Instead, they transmit the data
|
|
directly across the network.
|
|
|
|
In addition, ProtocolCmRegisterSap should perform any necessary allocations
|
|
of dynamic resources and structures that the call manager needs to maintain
|
|
state information about the SAP on behalf of the connection-oriented client.
|
|
Such resources include, but are not limited to, memory buffers, data
|
|
structures, events, and other such similar resources. A call manager must
|
|
also initialize any resources it allocates before returning control to NDIS.
|
|
Call managers must store the NDIS-supplied handle identifying the SAP,
|
|
provided at NdisSapHandle, in their context area for future use.
|
|
|
|
If ProtocolCmRegisterSap will return NDIS_STATUS_SUCCESS, it should, after
|
|
allocating the per-SAP state area, set the address of this state area in
|
|
CallMgrSapContext before returning control to NDIS. To do this, dereference
|
|
CallMgrSapContext and store a pointer to the data area as the value of the
|
|
handle. For example:
|
|
|
|
*CallMgrSapContext = SomeBuffer; // We use <t BCHANNEL_OBJECT>.
|
|
|
|
If the given SAP that is already registered by another connection-oriented
|
|
client, the call manager must fail the request and return
|
|
NDIS_STATUS_INVALID_DATA.
|
|
|
|
After a call manager has registered a SAP on behalf of a connection-oriented
|
|
client, it notifies that client of an incoming call offer directed to that
|
|
SAP by calling NdisCmDispatchIncomingCall.
|
|
|
|
ProtocolCmRegisterSap must be written so that it can run at IRQL DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCmRegisterSap returns the status of its operation(s) as one of the
|
|
following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager successfully allocated and/or initialized
|
|
any necessary resources to register and maintain the SAP. In addition, it
|
|
also indicates that the SAP was registered successfully as required by the
|
|
network media that the call manager supports.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the call manager will complete the processing of this request
|
|
asynchronously. Call managers must call NdisCmRegisterSapComplete when all
|
|
processing has been completed to signal NDIS that the registration is
|
|
finished.
|
|
|
|
@rvalue NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the call manager was unable to allocated and/or initialize
|
|
its resources required to register the SAP on behalf of the
|
|
connection-oriented client.
|
|
|
|
@rvalue NDIS_STATUS_INVALID_DATA |
|
|
|
|
Indicates that the specification provided at Sap is invalid or cannot be
|
|
supported.
|
|
|
|
@rvalue NDIS_STATUS_XXX |
|
|
|
|
Indicates that the call manager encountered an error in attempting to
|
|
register the SAP for the connection-oriented client. The return code is
|
|
appropriate to the error and could be a return code propagated from another
|
|
NDIS library function.
|
|
|
|
@xref
|
|
|
|
NdisCmDispatchIncomingCall, NdisCmRegisterSapComplete, NdisCoSendPackets,
|
|
<f ProtocolCmDeregisterSap>, <f ProtocolCmOpenAf>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmRegisterSap(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f ProtocolCmOpenAf>. AKA CallMgrAfContext.<nl>
|
|
// Specifies the handle to a call-manager allocated context area in which
|
|
// the call manager maintains its per-open AF state. The call manager
|
|
// supplied this handle to NDIS from its ProtocolCmOpenAf function.
|
|
|
|
IN PCO_SAP Sap, // @parm
|
|
// Points to a media-specific CO_SAP structure that contains the specific
|
|
// SAP that a connection-oriented client is registering.
|
|
|
|
IN NDIS_HANDLE NdisSapHandle, // @parm
|
|
// Specifies a handle, supplied by NDIS, that uniquely identifies this SAP.
|
|
// This handle is opaque to the call manager and reserved for NDIS library
|
|
// use.
|
|
|
|
OUT PNDIS_HANDLE CallMgrSapContext // @parm
|
|
// On return, specifies the handle to a call manager-supplied context area
|
|
// in which the call manager maintains state about this SAP. We will
|
|
// return a pointer to the <t BCHANNEL_OBJECT> instance identified by this
|
|
// SAP's lineID.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmRegisterSap")
|
|
|
|
PCO_AF_TAPI_SAP pTapiSap = (PCO_AF_TAPI_SAP) Sap->Sap;
|
|
|
|
PBCHANNEL_OBJECT pBChannel;
|
|
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
if (pTapiSap->ulLineID < pAdapter->NumBChannels)
|
|
{
|
|
pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter, pTapiSap->ulLineID);
|
|
|
|
if (pBChannel->NdisSapHandle != NULL)
|
|
{
|
|
// A SAP has already been registered and it doesn't make any sense to
|
|
// accept another since there are no SAP parameters to distinguish
|
|
// them.
|
|
DBG_ERROR(pAdapter, ("#%d Attempting to register SAP again!\n",
|
|
pBChannel->ObjectID));
|
|
Result = NDIS_STATUS_SAP_IN_USE;
|
|
}
|
|
else
|
|
{
|
|
pBChannel->NdisSapHandle = NdisSapHandle;
|
|
|
|
ASSERT(Sap->SapType == AF_TAPI_SAP_TYPE);
|
|
ASSERT(Sap->SapLength == sizeof(CO_AF_TAPI_SAP));
|
|
pBChannel->NdisTapiSap = *pTapiSap;
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d SAP=0x%X ulLineID=0x%X ulAddressID=0x%X ulMediaModes=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
NdisSapHandle,
|
|
pBChannel->NdisTapiSap.ulLineID,
|
|
pBChannel->NdisTapiSap.ulAddressID,
|
|
pBChannel->NdisTapiSap.ulMediaModes
|
|
));
|
|
|
|
// If this BChannel is currently on the available list, move it
|
|
// to the end of the list, so listening BChannels can be easily
|
|
// allocated to incoming calls from the end of the list.
|
|
NdisAcquireSpinLock(&pAdapter->EventLock);
|
|
if (!IsListEmpty(&pBChannel->LinkList))
|
|
{
|
|
RemoveEntryList(&pBChannel->LinkList);
|
|
InsertTailList(&pAdapter->BChannelAvailableList,
|
|
&pBChannel->LinkList);
|
|
}
|
|
NdisReleaseSpinLock(&pAdapter->EventLock);
|
|
|
|
// Since we return NDIS_STATUS_PENDING here, we must call
|
|
// NdisMCmRegisterSapComplete to complete this request.
|
|
// TODO: If necessary, you can do the completion asynchronously.
|
|
*CallMgrSapContext = pBChannel;
|
|
CompleteCmRegisterSap(pBChannel, NDIS_STATUS_SUCCESS);
|
|
Result = NDIS_STATUS_PENDING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERROR(pAdapter, ("Attempting to register invalid SAP=%d\n",
|
|
pTapiSap->ulLineID));
|
|
Result = NDIS_STATUS_INVALID_DATA;
|
|
}
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c CompleteCmDeregisterSap
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f CompleteCmDeregisterSap> is called when the miniport is done processing
|
|
the <f ProtocolCmDeregisterSap> request.
|
|
|
|
@comm
|
|
|
|
If you return NDIS_STATUS_PENDING from <f ProtocolCmDeregisterSap>, you
|
|
must call <f CompleteCmDeregisterSap> so that
|
|
<f NdisMCmDeregisterSapComplete> can be called to complete the request.
|
|
*/
|
|
|
|
VOID CompleteCmDeregisterSap(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
|
|
|
|
IN NDIS_STATUS Status // @parm
|
|
// The NDIS status code to be passed to NdisMCmRegisterSapComplete.
|
|
)
|
|
{
|
|
DBG_FUNC("CompleteCmDeregisterSap")
|
|
|
|
NDIS_HANDLE NdisSapHandle;
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
NdisSapHandle = pBChannel->NdisSapHandle;
|
|
pBChannel->NdisSapHandle = NULL;
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d SAP=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
NdisSapHandle
|
|
));
|
|
|
|
NdisMCmDeregisterSapComplete(Status, NdisSapHandle);
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmDeregisterSap
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmDeregisterSap> is a required function that is called by NDIS
|
|
to request that a call manager deregister a SAP on behalf of a
|
|
connection-oriented client.
|
|
|
|
@comm
|
|
|
|
ProtocolCmDeregisterSap communicates with network control devices or other
|
|
media-specific agents, as necessary, to deregister the SAP on the network.
|
|
Such actions could include, but are not limited to:
|
|
|
|
Communicating with a switching hardware
|
|
Communicating with a network control station
|
|
Communicating with other media-specific network agents
|
|
|
|
If a call manager is required to communicate with networking control agents,
|
|
such as a network switch, it should use a virtual connection to the network
|
|
control agent that it established in its ProtocolBindAdapter function.
|
|
Standalone call managers communicate through the underlying NIC miniport by
|
|
calling NdisCoSendPackets. NIC miniports that provide integrated
|
|
call-management support never call NdisCoSendPackets. Instead, they transmit
|
|
the data directly across the network.
|
|
|
|
In addition, ProtocolCmDeregisterSap must free any dynamically-allocated
|
|
resources in its per-SAP area, provided at CallMgrSapContext, as well as
|
|
freeing the state area itself before returning control to NDIS.
|
|
|
|
ProtocolCmDeregisterSap must be written such that it can be run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCmDeregisterSap returns the status of its operation(s) as one of the
|
|
following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager successfully removed the SAP registration
|
|
and freed any resources allocated to maintain per-SAP information.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the call manager will complete the request to deregister the
|
|
SAP asynchronously. The call manager must call NdisCmDeregisterSapComplete
|
|
to signal NDIS when the operation is complete.
|
|
|
|
@xref
|
|
|
|
NdisCmDeregisterSapComplete, NdisCoSendPackets, ProtocolBindAdapter,
|
|
<f ProtocolCmRegisterSap>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmDeregisterSap(
|
|
IN PBCHANNEL_OBJECT pBChannel // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCmRegisterSap>. AKA CallMgrSapContext.<nl>
|
|
// Specifies the handle to a call-manager allocated context area in which
|
|
// the call manager maintains its per-SAP state information. The call
|
|
// manager supplied this handle to NDIS from its ProtocolCmRegisterSap
|
|
// function.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmDeregisterSap")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// Since we return NDIS_STATUS_PENDING here, we must call
|
|
// NdisMCmDeregisterSapComplete to complete this request.
|
|
// TODO: If necessary, you can do the completion asynchronously.
|
|
CompleteCmDeregisterSap(pBChannel, NDIS_STATUS_SUCCESS);
|
|
Result = NDIS_STATUS_PENDING;
|
|
|
|
// If you return NDIS_STATUS_PENDING here, you must call
|
|
// NdisMCmDeregisterSapComplete to complete this request.
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL BChannel BChannel_c ProtocolCoCreateVc
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCoCreateVc> is a required function for connection-oriented
|
|
miniports. <f ProtocolCoCreateVc> is called by NDIS to indicate to
|
|
the miniport that a new VC is being created.
|
|
|
|
@comm
|
|
|
|
ProtocolCoCreateVc must be written as a synchronous function and cannot,
|
|
under any circumstances, return NDIS_STATUS_PENDING without causing a
|
|
system-wide failure.
|
|
|
|
ProtocolCoCreateVc allocates any necessary resources that the miniport
|
|
requires to maintain state information about the VC. The resources could
|
|
include, but are not limited to memory buffers, events, data structures,
|
|
and other such similar resources.
|
|
|
|
After allocating all required resources the miniport should initialize the
|
|
resources into a usable state and return a pointer to the state area in
|
|
MiniportVcContext. The handle is set by dereferencing the handle and
|
|
storing a pointer to the state buffer as the value of the handle. For
|
|
example:
|
|
|
|
*MiniportVcContext = SomeBuffer; // We use <t BCHANNEL_OBJECT>.
|
|
|
|
Miniport drivers must store the handle to the VC, NdisVcHandle, in their
|
|
state area as it is a required parameter to other NDIS library routines
|
|
that are subsequently called by the miniport.
|
|
|
|
ProtocolCoCreateVc must be written such that it can be run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
Call managers or clients cannot return NDIS_STATUS_PENDING from their
|
|
ProtocolCoCreateVc functions. Returning pending will render this virtual
|
|
connection unusable and the NDIS library will call the client or call
|
|
manager to delete it.
|
|
|
|
ProtocolCoCreateVc returns the status of its operation(s) as one of the
|
|
following values:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager or client successfully allocated and/or
|
|
initialized any necessary resources that were needed to establish and
|
|
maintain a virtual connection.
|
|
|
|
@rvalue NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the call manager or client was unable to allocate and/or
|
|
initialize its resources for establishing and maintaining a virtual
|
|
connection.
|
|
|
|
@rvalue NDIS_STATUS_XXX |
|
|
|
|
Indicates that the call manager or client could not set itself into a state
|
|
where it could establish a virtual connection. This can could be an error
|
|
return value propagated from another NDIS library routine.
|
|
|
|
@xref
|
|
|
|
<f MiniportInitialize>, NdisMSetAttributes, NdisMSetAttributesEx,
|
|
<f ProtocolCoDeleteVc>, <f MiniportCoActivateVc>, <f MiniportCoDeactivateVc>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCoCreateVc(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>. AKA ProtocolAfContext.<nl>
|
|
|
|
IN NDIS_HANDLE NdisVcHandle, // @parm
|
|
// Specifies a handle, supplied by NDIS, that uniquely identifies
|
|
// the VC being created. This handle is opaque to the miniport
|
|
// and reserved for NDIS library use.
|
|
|
|
OUT PBCHANNEL_OBJECT * ppBChannel // @parm
|
|
// Specifies, on output, a handle to a miniport-supplied context
|
|
// area in which the miniport maintains state about the VC.
|
|
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCoCreateVc")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_VC_NOT_AVAILABLE;
|
|
// Holds the result code returned by this function.
|
|
|
|
PBCHANNEL_OBJECT pBChannel = NULL;
|
|
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
|
|
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
ASSERT(ppBChannel);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// Allocate BChannel for VC based on whether it's incoming or outgoing.
|
|
#if defined(SAMPLE_DRIVER)
|
|
if (NdisVcHandle == NULL)
|
|
{
|
|
// The calling side has already removed the BChannel from the available
|
|
// list, so we just need to use it.
|
|
ASSERT(ppBChannel && *ppBChannel && (*ppBChannel)->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pBChannel = *ppBChannel;
|
|
}
|
|
else
|
|
{
|
|
#endif // SAMPLE_DRIVER
|
|
|
|
NdisAcquireSpinLock(&pAdapter->EventLock);
|
|
if (!IsListEmpty(&pAdapter->BChannelAvailableList))
|
|
{
|
|
if (NdisVcHandle)
|
|
{
|
|
// Pull from the head of the available list, so we can avoid
|
|
// using the BChannels that are setup with listening SAPs at
|
|
// the end of the list.
|
|
pBChannel = (PBCHANNEL_OBJECT) RemoveHeadList(
|
|
&pAdapter->BChannelAvailableList);
|
|
// Reset the link info so we can tell that it's not on the list.
|
|
InitializeListHead(&pBChannel->LinkList);
|
|
}
|
|
else
|
|
{
|
|
// Pull from the tail of the available list, to see if there
|
|
// are any listening SAPs that can accept this call.
|
|
pBChannel = (PBCHANNEL_OBJECT) RemoveTailList(
|
|
&pAdapter->BChannelAvailableList);
|
|
// Reset the link info so we can tell that it's not on the list.
|
|
InitializeListHead(&pBChannel->LinkList);
|
|
if (pBChannel->NdisSapHandle)
|
|
{
|
|
// TODO: You should look to make sure the incoming call matches
|
|
// the SAP of the listener. The sample driver just assumes it.
|
|
}
|
|
else
|
|
{
|
|
// Sorry, no one up there wants to hear about it.
|
|
InsertTailList(&pAdapter->BChannelAvailableList,
|
|
&pBChannel->LinkList);
|
|
pBChannel = NULL;
|
|
}
|
|
}
|
|
}
|
|
NdisReleaseSpinLock(&pAdapter->EventLock);
|
|
|
|
#if defined(SAMPLE_DRIVER)
|
|
}
|
|
#endif // SAMPLE_DRIVER
|
|
|
|
if (pBChannel == NULL)
|
|
{
|
|
DBG_ERROR(pAdapter, ("BChannelAvailableList is empty\n"));
|
|
}
|
|
else if (BChannelOpen(pBChannel, NdisVcHandle) == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Result = NDIS_STATUS_SUCCESS;
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState,
|
|
Result
|
|
));
|
|
}
|
|
else
|
|
{
|
|
// BChannel was already open - this should never happen...
|
|
DBG_ERROR(pAdapter,("BChannelOpen failed, but it should be availble\n"));
|
|
NdisAcquireSpinLock(&pAdapter->EventLock);
|
|
if (NdisVcHandle)
|
|
{
|
|
// Put it back on the head of the available list.
|
|
InsertHeadList(&pAdapter->BChannelAvailableList,
|
|
&pBChannel->LinkList);
|
|
}
|
|
else
|
|
{
|
|
// Put it back on the tail of the available list.
|
|
InsertTailList(&pAdapter->BChannelAvailableList,
|
|
&pBChannel->LinkList);
|
|
}
|
|
NdisReleaseSpinLock(&pAdapter->EventLock);
|
|
pBChannel = NULL;
|
|
}
|
|
*ppBChannel = pBChannel;
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL BChannel BChannel_c ProtocolCoDeleteVc
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCoDeleteVc> is a required function for connection-oriented
|
|
miniports. <f ProtocolCoDeleteVc> indicates that a VC is being torn
|
|
down and deleted by NDIS.
|
|
|
|
@comm
|
|
|
|
ProtocolCoDeleteVc must be written as a synchronous function and cannot,
|
|
under any circumstances, return NDIS_STATUS_PENDING without causing a
|
|
system-wide failure.
|
|
|
|
ProtocolCoDeleteVc frees any resources allocated on a per-VC basis and
|
|
stored in the context area MiniportVcContext. The miniport must also free
|
|
the MiniportVcContext that is allocated in its ProtocolCoCreateVc
|
|
function.
|
|
|
|
<f ProtocolCoDeleteVc> must be written such that it can be run from IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCoDeleteVc can return one of the following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
The protocol has released or prepared for reuse all the resources that it
|
|
originally allocated for the VC.
|
|
|
|
@rvalue NDIS_STATUS_NOT_ACCEPTED |
|
|
|
|
The VC is still active and the protocol has outstanding operations pending
|
|
on the VC so it could not be destroyed.
|
|
|
|
@rvalue NDIS_STATUS_XXX |
|
|
|
|
The protocol failed the VC deletion for a driver-determined reason.
|
|
|
|
@xref
|
|
|
|
NdisClCloseCall, NdisCmDispatchIncomingCloseCall, NdisCoCreateVc,
|
|
NdisCoDeleteVc, <f ProtocolCoCreateVc>, <f MiniportCoActivateVc>,
|
|
<f MiniportCoDeactivateVc>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCoDeleteVc(
|
|
IN PBCHANNEL_OBJECT pBChannel // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>. AKA ProtocolVcContext.<nl>
|
|
// Specifies the handle to the client's or call manager's per-VC context
|
|
// area. The protocol originally supplied this handle from its
|
|
// <f ProtocolCoCreateVc> function.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCoDeleteVc")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState,
|
|
Result
|
|
));
|
|
|
|
BChannelClose(pBChannel);
|
|
NdisAcquireSpinLock(&pAdapter->EventLock);
|
|
if (pBChannel->NdisSapHandle)
|
|
{
|
|
// Listening BChannels are kept at the end of the list.
|
|
InsertTailList(&pAdapter->BChannelAvailableList, &pBChannel->LinkList);
|
|
}
|
|
else
|
|
{
|
|
// Non-listening BChannels are kept at the end of the list.
|
|
InsertHeadList(&pAdapter->BChannelAvailableList, &pBChannel->LinkList);
|
|
}
|
|
NdisReleaseSpinLock(&pAdapter->EventLock);
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL Link Link_c MiniportCoActivateVc
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f MiniportCoActivateVc> is a required function for connection-oriented
|
|
miniports. <f MiniportCoActivateVc> is called by NDIS to indicate to the
|
|
miniport that a virtual connection is being activated.
|
|
|
|
@comm
|
|
|
|
The miniport driver must validate the call parameters for this VC, as
|
|
specified in CallParameters, to verify that the adapter can support the
|
|
requested call. If the requested call parameters cannot be satisfied, the
|
|
miniport should fail the request with NDIS_STATUS_INVALID_DATA.
|
|
|
|
MiniportCoActivateVc can be called many times for a single VC in order to
|
|
change the call parameters for an already active call. At every call, the
|
|
miniport should validate the parameters and perform any processing as
|
|
required by its adapter in order to satisfy the request. However, if it
|
|
cannot set the given call parameters, MiniportCoActivateVc must leave the
|
|
VC in a usable state, because the connection-oriented client or a call
|
|
manager can continue to send or receive data using the older call
|
|
parameters.
|
|
|
|
If the ROUND_UP_FLOW or ROUND_DOWN_FLOW flags are set in the call
|
|
parameters structure at CallParameters-\>MediaParameters-\>Flags, the
|
|
miniport has been requested to return the actual flow rate of the VC after
|
|
the flow rate has been rounded according to the appropriate flag that has
|
|
been set. If the miniport does change any of the call parameters because
|
|
these flags have been set, it must return the actual call parameters in
|
|
use for the VC at CallParameters.
|
|
|
|
If the call parameters are acceptable, MiniportCoActivateVc communicates
|
|
with its adapter as necessary to prepare the adapter to receive or
|
|
transmit data across the virtual connection (e.g. programming receive
|
|
buffers).
|
|
|
|
MiniportCoActivateVc must be written so that it can be run from IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
MiniportCoActivateVc can return one of the following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the VC was activated successfully.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the miniport will complete the request to activate a VC
|
|
asynchronously. When the miniport has finished with its operations, it must
|
|
call NdisMCoActivateVcComplete.
|
|
|
|
@rvalue NDIS_STATUS_INVALID_DATA |
|
|
|
|
Indicates that the call parameters specified at CallParameters are invalid
|
|
or illegal for the media type that this miniport supports.
|
|
|
|
@rvalue NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the miniport could not activate the VC because it could not
|
|
allocate all of the required resources that the miniport needs to maintain
|
|
state information about the active VC.
|
|
|
|
@xref
|
|
|
|
<f ProtocolCoCreateVc>, <f MiniportCoDeactivateVc>, NdisMCoActivateVcComplete
|
|
*/
|
|
|
|
NDIS_STATUS MiniportCoActivateVc(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>. AKA MiniportVcContext.<nl>
|
|
// Specifies the handle to a miniport-allocated context area in which the
|
|
// miniport maintains its per-VC state. The miniport supplied this handle
|
|
// to NDIS from its <f ProtocolCoCreateVc> function.
|
|
|
|
IN OUT PCO_CALL_PARAMETERS pCallParameters // @parm
|
|
// A pointer to the <t CO_CALL_PARAMETERS>
|
|
// Specifies the call parameters, as specified by the call manager, to be
|
|
// established for this VC. On output, the miniport returns altered call
|
|
// parameters if certain flags are set in the CO_CALL_PARAMETERS structure.
|
|
)
|
|
{
|
|
DBG_FUNC("MiniportCoActivateVc")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// TODO: Add code here if needed
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL Link Link_c MiniportCoDeactivateVc
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f MiniportCoDeactivateVc> is a required function for connection-oriented
|
|
miniports. <f MiniportCoDeactivateVc> is called by NDIS to indicate that
|
|
a VC is being marked as unusable.
|
|
|
|
@comm
|
|
|
|
MiniportCoDeactivateVc communicates with its network adapter to terminate
|
|
all communication across this VC (e.g. deprogramming receive or send buffers
|
|
on the adapter). The miniport should also mark the VC, it its context area,
|
|
as being inactive to prevent any further communication across the VC.
|
|
|
|
There is not a one-to-one relationship between calls to MiniportCoActivateVc
|
|
and MiniportCoDeactivateVc. While NDIS may call MiniportCoActivateVc
|
|
multiple times on a single VC, only one call to MiniportCoDeactivateVc is
|
|
made to shut down a virtual connection. For example, a VC can be reused for
|
|
different calls possibly causing multiple calls to MiniportCoActivateVc.
|
|
|
|
@rdesc
|
|
|
|
MiniportCoDeactivateVc can return one of the following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the miniport successfully halted any communication across the
|
|
VC and marked it as unusable.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the miniport will complete the request to halt the VC
|
|
asynchronously. When the miniport has completed halting the VC, it must then
|
|
call NdisMCoDeactivateVcComplete to signal NDIS that this operation has been
|
|
completed.
|
|
|
|
@xref
|
|
|
|
<f MiniportCoActivateVc>, NdisMCoDeactivateVcComplete
|
|
*/
|
|
|
|
NDIS_STATUS MiniportCoDeactivateVc(
|
|
IN PBCHANNEL_OBJECT pBChannel // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>. AKA MiniportVcContext.<nl>
|
|
// Specified the handle to a miniport-allocated context area in which the
|
|
// miniport maintains state information per-VC. The miniport supplied this
|
|
// handle to NDIS from its <f ProtocolCoCreateVc> function.
|
|
|
|
)
|
|
{
|
|
DBG_FUNC("MiniportCoDeactivateVc")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// TODO: Add code here if needed
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c CompleteCmMakeCall
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f CompleteCmMakeCall> is called when the miniport is done processing the
|
|
<f ProtocolCmMakeCall> request.
|
|
|
|
@comm
|
|
|
|
If you return NDIS_STATUS_PENDING from <f ProtocolCmMakeCall>, you must
|
|
call <f CompleteCmMakeCall> so that <f NdisMCmMakeCallComplete>
|
|
can be called to complete the request.
|
|
|
|
This routine also activates the VC and marks the call state as connected.
|
|
*/
|
|
|
|
VOID CompleteCmMakeCall(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
|
|
|
|
IN NDIS_STATUS Status // @parm
|
|
// Status to return to <f NdisMCmMakeCallComplete>. If status does not
|
|
// equal NDIS_STATUS_SUCCESS, the call is closed and the BChannel is
|
|
// released.
|
|
)
|
|
{
|
|
DBG_FUNC("CompleteCmMakeCall")
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState,
|
|
Status
|
|
));
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pBChannel->pOutCallParms->CallMgrParameters->Receive.PeakBandwidth =
|
|
pBChannel->pOutCallParms->CallMgrParameters->Transmit.PeakBandwidth =
|
|
pBChannel->LinkSpeed/8;
|
|
|
|
Status = NdisMCmActivateVc(pBChannel->NdisVcHandle,
|
|
pBChannel->pOutCallParms);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pBChannel->Flags |= VCF_VC_ACTIVE;
|
|
pBChannel->CallState = LINECALLSTATE_CONNECTED;
|
|
}
|
|
else
|
|
{
|
|
DBG_ERROR(pAdapter,("NdisMCmActivateVc Error=0x%X\n",Status));
|
|
}
|
|
}
|
|
NdisMCmMakeCallComplete(Status, pBChannel->NdisVcHandle,
|
|
NULL, NULL,
|
|
pBChannel->pOutCallParms);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
// The call failed, so cleanup and bail out.
|
|
pBChannel->Flags &= ~VCF_OUTGOING_CALL;
|
|
}
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmMakeCall
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmMakeCall> is a required function that sets up media specific
|
|
parameters for a virtual connection (VC) and activates the virtual
|
|
connection.
|
|
|
|
@comm
|
|
|
|
If ProtocolCmMakeCall is given an explicit NdisPartyHandle, this VC was
|
|
created by the client for a multipoint call. The call manager must allocate
|
|
and initialize any necessary resources required to maintain state
|
|
information and control a multipoint call. Such resources include, but are
|
|
not limited to, memory buffers, data structures, events, and other similar
|
|
resources. If the call manager cannot allocate or initialize the needed
|
|
resources for its state area(s), it should return control to NDIS with
|
|
NDIS_STATUS_RESOURCES.
|
|
|
|
ProtocolCmMakeCall communicates with network control devices or other
|
|
media-specific actors, as necessary, to make a connection between the local
|
|
node and a remote node based on the call parameters specified at
|
|
CallParameters. Such actions could include, but are not limited to,
|
|
communication with switching hardware, communications with a network control
|
|
station, or other actions as appropriate to the network medium.
|
|
|
|
If a call manager is required to communication with networking hardware
|
|
(e.g. a networking switch) it should use a virtual connection to the network
|
|
control device that it established in its ProtocolBindAdapter function. Call
|
|
managers communicate with their network hardware through the miniport driver
|
|
by calling NdisCoSendPackets. NIC miniports with integrated call-management
|
|
support will not call NdisCoSendPackets, but rather will transmit the data
|
|
themselves.
|
|
|
|
After a call manager has done all necessary communication with its
|
|
networking hardware as required by its medium, call managers must call
|
|
NdisCmActivateVc.
|
|
|
|
If this call was a multipoint call, after the call manager has communicated
|
|
with the networking hardware, verified call parameters, and allocated and
|
|
initialized its per-party state data, the address of its state block should
|
|
be set in the handle CallMgrPartyContext before returning control to NDIS.
|
|
The handle is set by dereferencing the handle and storing a pointer to the
|
|
state block as the value of the handle. For example:
|
|
|
|
*CallMgrPartyContext = SomeBuffer; // We use NULL
|
|
|
|
If ProtocolCmMakeCall has completed the required operations for its network
|
|
and the VC has been successfully activated through NdisCmActivateVc,
|
|
ProtocolCmMakeCall should return control as quickly as possible with a
|
|
status of NDIS_STATUS_SUCCESS.
|
|
|
|
After ProtocolCmMakeCall returns control to NDIS, the call manager should
|
|
expect to take no further actions on this call to set it up.
|
|
ProtocolCmMakeCall is responsible for establishing the connection so that
|
|
the client can make data transfers over the network on this VC. However, the
|
|
call manager can be called subsequently to modify the call's quality of
|
|
service, to add or drop parties if this is a multipoint VC, and eventually
|
|
to terminate this call.
|
|
|
|
ProtocolCmMakeCall must be written so that it can run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
<f ProtocolCmMakeCall> returns the status of its operation(s) as one of
|
|
the following values:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager successfully allocated the necessary
|
|
resources to make the call and was able to activate the virtual connection
|
|
with the miniport driver.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the call manager will complete the request to make a call
|
|
asynchronously. When the call manager has completed all operations for
|
|
making a call, it must call NdisCmMakeCallComplete to signal NDIS that this
|
|
call has been completed.
|
|
|
|
@rvalue NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the call manager was unable to allocate and/or initialize its
|
|
resources for activating the virtual connection as requested by the client.
|
|
|
|
@rvalue NDIS_STATUS_NOT_SUPPORTED |
|
|
|
|
Indicates that the call manager was unable to activate a virtual connection
|
|
because the caller requested invalid or unavailable features in the call
|
|
parameters specified at CallParameters.
|
|
|
|
@xref
|
|
|
|
NdisClMakeCall, NdisCmActivateVc, NdisCmMakeCallComplete,
|
|
<f ProtocolCoCreateVc>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmMakeCall(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>. AKA CallMgrVcContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call managers maintains its per-VC state. The call manager supplied
|
|
// this handle to NDIS from its ProtocolCoCreateVc function.
|
|
|
|
IN OUT PCO_CALL_PARAMETERS pCallParameters, // @parm
|
|
// Points to a CO_CALL_PARAMETERS structure that contains the parameters,
|
|
// specified by a connection-oriented client, for this outgoing call.
|
|
|
|
IN NDIS_HANDLE NdisPartyHandle, // @parm
|
|
// Specifies a handle, supplied by NDIS, that uniquely identifies the
|
|
// initial party on the multipoint virtual connection. This handle is
|
|
// opaque to the call manager and reserved for NDIS library use. This
|
|
// handle is NULL if the client is not setting up an outgoing multipoint
|
|
// call.
|
|
|
|
OUT PNDIS_HANDLE CallMgrPartyContext // @parm
|
|
// On return, specifies a handle to a call manager-supplied context area in
|
|
// which the call manager maintains state about the initial party on the
|
|
// multipoint call. If NdisPartyHandle is NULL, this handle must be set to
|
|
// NULL.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmMakeCall")
|
|
|
|
PCO_AF_TAPI_MAKE_CALL_PARAMETERS pTapiCallParameters;
|
|
// Points to the TAPI call parameters contained in pCallParameters.
|
|
|
|
PLINE_CALL_PARAMS pLineCallParams;
|
|
// Points to the LINE call parameters contained in pTapiCallParameters.
|
|
|
|
USHORT DialStringLength;
|
|
// Length of the dial string in bytes.
|
|
|
|
PUSHORT pDialString;
|
|
// Points to the dial string contained in pTapiCallParameters.
|
|
|
|
UCHAR DialString[CARD_MAX_DIAL_DIGITS+1];
|
|
// Temporary copy of dial string. One extra for NULL terminator.
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// Check a few preconditions ;) Maybe the NDPROXY will change the rules
|
|
// someday, and we'll have to change our assumptions...
|
|
ASSERT(NdisPartyHandle == NULL);
|
|
ASSERT(pCallParameters->Flags == 0);
|
|
ASSERT(pCallParameters->CallMgrParameters);
|
|
ASSERT(pCallParameters->CallMgrParameters->Transmit.TokenRate ==
|
|
pBChannel->LinkSpeed/8);
|
|
ASSERT(pCallParameters->CallMgrParameters->Receive.TokenRate ==
|
|
pBChannel->LinkSpeed/8);
|
|
ASSERT(pCallParameters->CallMgrParameters->CallMgrSpecific.ParamType == 0);
|
|
ASSERT(pCallParameters->CallMgrParameters->CallMgrSpecific.Length == 0);
|
|
ASSERT(pCallParameters->MediaParameters);
|
|
ASSERT(pCallParameters->MediaParameters->Flags & TRANSMIT_VC);
|
|
ASSERT(pCallParameters->MediaParameters->Flags & RECEIVE_VC);
|
|
ASSERT(pCallParameters->MediaParameters->ReceiveSizeHint >=
|
|
pAdapter->pCard->BufferSize);
|
|
ASSERT(pCallParameters->MediaParameters->MediaSpecific.ParamType == 0);
|
|
ASSERT(pCallParameters->MediaParameters->MediaSpecific.Length >=
|
|
sizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS));
|
|
pTapiCallParameters = (PCO_AF_TAPI_MAKE_CALL_PARAMETERS)
|
|
pCallParameters->MediaParameters->MediaSpecific.Parameters;
|
|
ASSERT(pTapiCallParameters->ulLineID < pAdapter->NumBChannels);
|
|
ASSERT(pTapiCallParameters->ulAddressID == TSPI_ADDRESS_ID);
|
|
ASSERT(pTapiCallParameters->ulFlags & CO_TAPI_FLAG_OUTGOING_CALL);
|
|
ASSERT(pTapiCallParameters->DestAddress.Length > sizeof(USHORT));
|
|
ASSERT(pTapiCallParameters->DestAddress.MaximumLength >=
|
|
pTapiCallParameters->DestAddress.Length);
|
|
ASSERT(pTapiCallParameters->DestAddress.Offset >=
|
|
sizeof(NDIS_VAR_DATA_DESC));
|
|
DialStringLength = pTapiCallParameters->DestAddress.Length;
|
|
pDialString = (PUSHORT)
|
|
((PUCHAR)&pTapiCallParameters->DestAddress +
|
|
pTapiCallParameters->DestAddress.Offset);
|
|
ASSERT(pTapiCallParameters->LineCallParams.Length >= sizeof(LINE_CALL_PARAMS));
|
|
ASSERT(pTapiCallParameters->LineCallParams.MaximumLength >=
|
|
pTapiCallParameters->LineCallParams.Length);
|
|
ASSERT(pTapiCallParameters->LineCallParams.Offset >=
|
|
sizeof(NDIS_VAR_DATA_DESC));
|
|
|
|
pLineCallParams = (PLINE_CALL_PARAMS)
|
|
((PUCHAR)&pTapiCallParameters->LineCallParams +
|
|
pTapiCallParameters->LineCallParams.Offset);
|
|
|
|
// This was useful for debugging the nested call parameter structures.
|
|
DBG_NOTICE(pAdapter,(
|
|
"\t\tsizeof(CO_CALL_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(CO_CALL_MANAGER_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(CO_MEDIA_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(LINE_CALL_PARAMS) =%03d\n",
|
|
"\t\tMaximumLength =%03d\n",
|
|
sizeof(CO_CALL_PARAMETERS),
|
|
sizeof(CO_CALL_MANAGER_PARAMETERS),
|
|
sizeof(CO_MEDIA_PARAMETERS),
|
|
sizeof(CO_AF_TAPI_MAKE_CALL_PARAMETERS),
|
|
sizeof(LINE_CALL_PARAMS),
|
|
pTapiCallParameters->LineCallParams.MaximumLength
|
|
));
|
|
|
|
/*
|
|
// TODO: The sample driver doesn't support multi-party calls.
|
|
*/
|
|
*CallMgrPartyContext = NULL;
|
|
|
|
/*
|
|
// Make sure the call parameters are valid for us.
|
|
*/
|
|
if (pLineCallParams->ulBearerMode & ~pBChannel->BearerModesCaps)
|
|
{
|
|
DBG_WARNING(pAdapter, ("TAPI_INVALBEARERMODE=0x%X\n",
|
|
pLineCallParams->ulBearerMode));
|
|
Result = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
else if (pLineCallParams->ulMediaMode & ~pBChannel->MediaModesCaps)
|
|
{
|
|
DBG_WARNING(pAdapter, ("TAPI_INVALMEDIAMODE=0x%X\n",
|
|
pLineCallParams->ulMediaMode));
|
|
Result = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
else if (pLineCallParams->ulMinRate > _64KBPS ||
|
|
pLineCallParams->ulMinRate > pLineCallParams->ulMaxRate)
|
|
{
|
|
DBG_WARNING(pAdapter, ("TAPI_INVALRATE=%d:%d\n",
|
|
pLineCallParams->ulMinRate,pLineCallParams->ulMaxRate));
|
|
Result = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
else if (pLineCallParams->ulMaxRate && pLineCallParams->ulMaxRate < _56KBPS)
|
|
{
|
|
DBG_WARNING(pAdapter, ("TAPI_INVALRATE=%d:%d\n",
|
|
pLineCallParams->ulMinRate,pLineCallParams->ulMaxRate));
|
|
Result = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
else if (DialStringLength == 0)
|
|
{
|
|
DBG_WARNING(pAdapter, ("TAPI_INVALPARAM=No dial string\n"));
|
|
Result = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// Dial the number, but don't include the null terminator.
|
|
*/
|
|
DialStringLength = CardCleanPhoneNumber(DialString,
|
|
pDialString,
|
|
DialStringLength);
|
|
|
|
if (DialStringLength > 0)
|
|
{
|
|
/*
|
|
// Save the call parameters.
|
|
*/
|
|
pBChannel->MediaMode = pLineCallParams->ulMediaMode;
|
|
pBChannel->BearerMode = pLineCallParams->ulBearerMode;
|
|
pBChannel->LinkSpeed = pLineCallParams->ulMaxRate == 0 ?
|
|
_64KBPS : pLineCallParams->ulMaxRate;
|
|
pBChannel->pOutCallParms = pCallParameters;
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X DIALING: '%s'\n"
|
|
"\tLineID=%d - AddressID=%d - "
|
|
"Rate=%d-%d - MediaMode=0x%X - BearerMode=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState,
|
|
DialString,
|
|
pTapiCallParameters->ulLineID,
|
|
pTapiCallParameters->ulAddressID,
|
|
pLineCallParams->ulMinRate,
|
|
pLineCallParams->ulMaxRate,
|
|
pLineCallParams->ulMediaMode,
|
|
pLineCallParams->ulBearerMode
|
|
));
|
|
|
|
// Now we're ready to tell the network about the call.
|
|
Result = DChannelMakeCall(pAdapter->pDChannel,
|
|
pBChannel,
|
|
DialString,
|
|
DialStringLength,
|
|
pLineCallParams);
|
|
|
|
if (Result != NDIS_STATUS_PENDING)
|
|
{
|
|
CompleteCmMakeCall(pBChannel, Result);
|
|
Result = NDIS_STATUS_PENDING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_WARNING(pAdapter, ("TAPI_INVALPARAM=Invalid dial string=%s\n",
|
|
pDialString));
|
|
Result = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c CompleteCmCloseCall
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f CompleteCmCloseCall> is called when the miniport is done processing the
|
|
<f ProtocolCmCloseCall> request.
|
|
|
|
@comm
|
|
|
|
If you return NDIS_STATUS_PENDING from <f ProtocolCmCloseCall>, you must
|
|
call <f CompleteCmCloseCall> so that <f NdisMCmCloseCallComplete>
|
|
can be called to complete the request.
|
|
|
|
Upon return from this routine, you can no longer access the BChannel/VC
|
|
as it has been deactivated and returned to the available pool.
|
|
*/
|
|
|
|
VOID CompleteCmCloseCall(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>.
|
|
|
|
IN NDIS_STATUS Status // @parm
|
|
// Status to return to <f NdisMCmCloseCallComplete>. Regardless of the
|
|
// status, the VC is deactivated and deleted.
|
|
)
|
|
{
|
|
DBG_FUNC("CompleteCmCloseCall")
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState, Status
|
|
));
|
|
|
|
// Deactivate the VC if needed.
|
|
if (pBChannel->Flags & VCF_VC_ACTIVE)
|
|
{
|
|
pBChannel->Flags &= ~VCF_VC_ACTIVE;
|
|
NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
|
|
}
|
|
|
|
// Tell NDPROXY we're done.
|
|
NdisMCmCloseCallComplete(Status, pBChannel->NdisVcHandle, NULL);
|
|
|
|
// If it was an incoming call, it's up to us to delete the VC.
|
|
if (pBChannel->Flags & VCF_INCOMING_CALL)
|
|
{
|
|
pBChannel->Flags &= ~VCF_INCOMING_CALL;
|
|
if (pBChannel->NdisVcHandle)
|
|
{
|
|
NdisMCmDeleteVc(pBChannel->NdisVcHandle);
|
|
pBChannel->NdisVcHandle = NULL;
|
|
ProtocolCoDeleteVc((NDIS_HANDLE) pBChannel);
|
|
}
|
|
}
|
|
else if (pBChannel->Flags & VCF_OUTGOING_CALL)
|
|
{
|
|
pBChannel->Flags &= ~VCF_OUTGOING_CALL;
|
|
}
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmCloseCall
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmCloseCall> is a required function that terminates an existing
|
|
call and releases any resources that the call manager allocated for the
|
|
call.
|
|
|
|
@comm
|
|
|
|
ProtocolCmCloseCall communicated with network control devices or other
|
|
media-specific actors, as necessitated by its media, to terminate a
|
|
connection between the local node and a remote node. If the call manager is
|
|
required to communicate with network control devices (e.g. a networking
|
|
switch) it should use a virtual connection to the network control device
|
|
that it established in its ProtocolBindAdapter function. Standalone call
|
|
managers communicate to such network devices by calling NdisCoSendPackets.
|
|
NIC miniports with integrated call-management support never call
|
|
NdisCoSendPackets. Instead, they transmit the data directly across the
|
|
network.
|
|
|
|
If CloseData is nonNULL and sending data at connection termination is
|
|
supported by the media that this call manager handles, the call manager
|
|
should transmit the data specified at CloseData to the remote node before
|
|
completing the call termination. If sending data concurrent with a
|
|
connection being terminated is not supported, call managers should return
|
|
NDIS_STATUS_INVALID_DATA.
|
|
|
|
If ProtocolCmCloseCall is passed an explicit CallMgrPartyContext, then the
|
|
call being terminated is a multipoint VC, and the call manager must perform
|
|
any necessary network communication with its networking hardware, as
|
|
appropriate to its media type, to terminate the call as a multipoint call.
|
|
The call manager must also free the memory that it allocated earlier, in
|
|
ProtocolCmMakeCall, for its per-party state that is pointed to by
|
|
CallMgrPartyContext. Failure to properly release, de-allocate, or otherwise
|
|
deactivate those resources causes a memory leak.
|
|
|
|
After the call has been terminated with the network, any close data has been
|
|
sent, and any resources at CallMgrPartyContext have been freed, the call
|
|
manager must call NdisCmDeactivateVc. This notifies NDIS and the underlying
|
|
NIC miniport, if any, to expect no further transfers on the given VC.
|
|
|
|
ProtocolCmCloseCall must be written so that it can run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCmCloseCall returns the status of its operation(s) as one of the
|
|
following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager successfully terminated the call.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the call manager will complete the request to terminate the
|
|
call asynchronously. When the call manager has completed all operations
|
|
required to terminate the connection, it must then call
|
|
NdisCmCloseCallComplete to signal NDIS that the call has been closed.
|
|
|
|
@rvalue NDIS_STATUS_INVALID_DATA |
|
|
|
|
Indicates that CloseData was specified, but the underlying network medium
|
|
does not support sending data concurrent with terminating a call.
|
|
|
|
@rvalue NDIS_STATUS_XXX |
|
|
|
|
Indicates that the call manager could not terminate the call. The actual
|
|
error returned can be a status propagated from another NDIS library routine.
|
|
|
|
@xref
|
|
|
|
NdisClMakeCall, NdisCmDeactivateVc, NdisCoSendPackets,
|
|
<f ProtocolCmMakeCall>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmCloseCall(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call manager maintains its per-VC state. This handle was provided to
|
|
// NDIS from the call managers <f ProtocolCmMakeCall> function.
|
|
|
|
IN NDIS_HANDLE CallMgrPartyContext, // @parm
|
|
// Specifies the handle, if any, to a call manager-allocated context area
|
|
// in which the call manager maintain information about a party on a
|
|
// multipoint VC. This handle is NULL if the call being closed is not a
|
|
// multipoint call.
|
|
|
|
IN PVOID CloseData, // @parm
|
|
// Points to a buffer containing connection-oriented client-specified data
|
|
// that should be sent across the connection before the call is terminated.
|
|
// This parameter is NULL if the underlying network medium does not support
|
|
// transfers of data when closing a connection.
|
|
|
|
IN UINT Size // @parm
|
|
// Specifies the length, in bytes, of the buffer at CloseData, zero if
|
|
// CloseData is NULL.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmCloseCall")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState
|
|
));
|
|
|
|
Result = DChannelCloseCall(pAdapter->pDChannel, pBChannel);
|
|
if (Result != NDIS_STATUS_PENDING)
|
|
{
|
|
CompleteCmCloseCall(pBChannel, Result);
|
|
Result = NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmIncomingCallComplete
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmIncomingCallComplete> is a required function that, when called
|
|
by NDIS, indicates to the call manager that the connection-oriented client
|
|
has finished processing of an incoming call offer that the call manager
|
|
previously dispatched through NdisCmDispatchIncomingCall.
|
|
|
|
@comm
|
|
|
|
When the connection-oriented client has completed processing of an incoming
|
|
connection offer that the call manager dispatched to it, this routine will
|
|
be called if NdisCmDispatchIncomingCall returned NDIS_STATUS_PENDING. The
|
|
final status of the incoming call is found in Status. Possible values for
|
|
Status include, but are not limited to:
|
|
|
|
@flag NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager has accepted the incoming call.
|
|
|
|
@flag NDIS_STATUS_FAILURE |
|
|
|
|
Indicates that either the address family or the SAP that the call dispatched
|
|
for is currently in the process of closing.
|
|
|
|
@flag NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the incoming call was not accepted because the
|
|
connection-oriented client was unable to dynamically allocate resources
|
|
required for it to process the call.
|
|
|
|
@flag NDIS_STATUS_INVALID_DATA |
|
|
|
|
Indicates that the connection-oriented client rejected the call because the
|
|
call parameters specified were invalid.
|
|
|
|
@normal
|
|
|
|
If the client accepts the incoming call, the call manager should send
|
|
signaling message(s) to indicate to the calling entity that the call has
|
|
been accepted. If the client does not accept the call, the call manager
|
|
should send signaling message(s) to indicate that the call has been
|
|
rejected.
|
|
|
|
ProtocolCmIncomingCallComplete must be written so that is can be run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@xref
|
|
|
|
NdisCmDispatchIncomingCall, ProtocolClIncomingCall, <f ProtocolCmRegisterSap>
|
|
*/
|
|
|
|
VOID ProtocolCmIncomingCallComplete(
|
|
IN NDIS_STATUS Status, // @parm
|
|
// Indicates the final status of the operation to dispatch an incoming call
|
|
// to a connection-oriented client.
|
|
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call manager maintains its per-VC state. The call manager supplied
|
|
// this handle from its <f ProtocolCoCreateVc> function.
|
|
|
|
IN PCO_CALL_PARAMETERS pCallParameters // @parm
|
|
// Points to the call parameters as specified by the call manager in the
|
|
// call to NdisCmDispatchIncomingCall. The signaling protocol determines
|
|
// which call parameters, if any, the call manager can change.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmIncomingCallComplete")
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState, Status
|
|
));
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
// We're not going to answer this call.
|
|
DChannelRejectCall(pAdapter->pDChannel, pBChannel);
|
|
|
|
if (pBChannel->Flags & VCF_VC_ACTIVE)
|
|
{
|
|
pBChannel->Flags &= ~VCF_VC_ACTIVE;
|
|
NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
|
|
}
|
|
|
|
if (pBChannel->NdisVcHandle)
|
|
{
|
|
NdisMCmDeleteVc(pBChannel->NdisVcHandle);
|
|
pBChannel->NdisVcHandle = NULL;
|
|
ProtocolCoDeleteVc((NDIS_HANDLE) pBChannel);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = DChannelAnswerCall(pAdapter->pDChannel, pBChannel);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pBChannel->CallState = LINECALLSTATE_CONNECTED;
|
|
NdisMCmDispatchCallConnected(pBChannel->NdisVcHandle);
|
|
}
|
|
else if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
InitiateCallTeardown(pAdapter, pBChannel);
|
|
}
|
|
}
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmActivateVcComplete
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmActivateVcComplete> is a required function that indicates to
|
|
the call manager that a previous call to NdisCoActivateVc has been completed
|
|
by the miniport.
|
|
|
|
@comm
|
|
|
|
When other network components have completed their operations for activating
|
|
a virtual connection, initiated when the call manager called
|
|
NdisCmActivateVc, NDIS notifies the call manager that the VC has been
|
|
activated by calling its ProtocolCmActivateVcComplete function. The status
|
|
of the activation is found in Status. Possible values for Status include,
|
|
but are not limited to:
|
|
|
|
@flag NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the VC completed successfully and the call manager can
|
|
continue operations on this VC as required by its media.
|
|
|
|
@flag NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that another component in the activation has failed to activate
|
|
the virtual connection because of a lack of memory or an inability allocate
|
|
another type of resource.
|
|
|
|
@flag NDIS_STATUS_NOT_ACCEPTED |
|
|
|
|
Indicates that an activation is currently pending on the virtual connection.
|
|
Only one activation can be processed at a time for a virtual connection. The
|
|
request to activate the VC should be tried again at a later time.
|
|
|
|
@flag NDIS_STATUS_CLOSING |
|
|
|
|
Indicates that a deactivation is pending on the VC and the VC is no longer
|
|
available for network communication until the deactivation has been
|
|
completed and a successful activation has taken place.
|
|
|
|
@flag NDIS_STATUS_INVALID_DATA |
|
|
|
|
Indicates that the miniport has rejected the call parameters at
|
|
CallParamters as invalid for the adapter.
|
|
|
|
@normal
|
|
|
|
ProtocolCmActivateVcComplete must check the status returned in Status to
|
|
ensure that the virtual connection has been activated successfully. The call
|
|
manager must not attempt to communicate over the virtual connection if
|
|
Status is not NDIS_STATUS_SUCCESS.
|
|
|
|
Call managers must complete any processing required by their network media
|
|
to ensure that the virtual connection is ready for data transmission before
|
|
returning control to NDIS.
|
|
|
|
If the call manager specified either ROUND_UP_FLOW or ROUND_DOWN_FLOW in the
|
|
CallParameters->MediaParamters->Flags, the call parameters returned in
|
|
CallParamters can have been changed by the miniport. Call managers should
|
|
examine the call parameters that were returned to ensure proper operation.
|
|
If the new call parameters are unsatisfactory, the call manager should
|
|
either call NdisCmActivateVc again with new call parameters or deactivate
|
|
the VC with NdisCmDeactivateVc.
|
|
|
|
ProtocolCmActivateVcComplete must be written so that it can run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@xref
|
|
|
|
NdisCmActivateVc, NdisCmDeactivateVc, <f ProtocolCmMakeCall>
|
|
*/
|
|
|
|
VOID ProtocolCmActivateVcComplete(
|
|
IN NDIS_STATUS Status, // @parm
|
|
// Specifies the final status, as indicated by the miniport, of the request
|
|
// by the call manager to activate a VC.
|
|
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call manager maintains its per-VC state. The call manager supplied
|
|
// this handle from its <f ProtocolCoCreateVc> function.
|
|
|
|
IN PCO_CALL_PARAMETERS pCallParameters // @parm
|
|
// Points the call parameters as specified by the call manager in a call to
|
|
// NdisCmActivateVc.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmActivateVcComplete")
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState, Status
|
|
));
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmDeactivateVcComplete
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmDeactivateVcComplete> is a required function that completes the
|
|
processing of a call-manager initiated request that the underlying miniport
|
|
(and NDIS) deactivate a VC for which NdisCmDeactivateVc previously returned
|
|
NDIS_STATUS_PENDING.
|
|
|
|
@comm
|
|
|
|
NDIS usually calls ProtocolCmDeactivateVcComplete in the context of the call
|
|
manager's closing down a call on behalf of a connection-oriented client. The
|
|
call manager typically calls NdisCmDeactivateVc from its ProtocolCmCloseCall
|
|
function. Whenever NdisCmDeactivateVc returns NDIS_STATUS_PENDING, NDIS
|
|
subsequently calls its ProtocolCmDeactivateVcComplete function.
|
|
|
|
That is, when the underlying connection-oriented miniport has deactivated
|
|
the VC, NDIS calls ProtocolCmDeactivateVcComplete. The final status of the
|
|
deactivation is found in Status. Possible values for the final status
|
|
include, but are not limited to:
|
|
|
|
@flag NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the VC was deactivated successfully.
|
|
|
|
@flag NDIS_STATUS_NOT_ACCEPTED |
|
|
|
|
Indicates that an activation is pending on this VC. The call manager should
|
|
attempt to deactivate the VC at a later time.
|
|
|
|
@flag NDIS_STATUS_CLOSING |
|
|
|
|
Indicates that a deactivation is currently pending on this VC. The call
|
|
manager need not call NdisCmDeactivateVc again as only one call to
|
|
NdisCmDeactivateVc is required to deactivate a VC.
|
|
|
|
@normal
|
|
|
|
ProtocolCmDeactivateVcComplete performs whatever postprocessing is necessary
|
|
to complete the deactivation of a virtual connection, such as setting flags
|
|
in its state area to indicate that the connection is inactive or releasing
|
|
dynamically allocated resources used while the VC is active.
|
|
|
|
Completion of the deactivation means that all call parameters for the VC
|
|
used on activation are no longer valid. Any further use of the VC is
|
|
prohibited except to reactivate it with a new set of call parameters.
|
|
|
|
Call managers should release any resources that were allocated for the VC
|
|
activation and return control as quickly as possible. If the call manager
|
|
previously returned NDIS_STATUS_PENDING from its ProtocolCmCloseCall
|
|
function and all operations to close the call have been completed,
|
|
ProtocolCmDeactivateVcComplete should now call NdisCmCloseCallComplete.
|
|
|
|
ProtocolCmDeactivateVcComplete must be written so that it can run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@xref
|
|
|
|
<f MiniportCoDeactivateVc>, NdisCmCloseCallComplete, NdisCmDeactivateVc,
|
|
<f ProtocolCmCloseCall>
|
|
*/
|
|
|
|
VOID ProtocolCmDeactivateVcComplete(
|
|
IN NDIS_STATUS Status, // @parm
|
|
// Specifies the final status of the deactivation.
|
|
|
|
IN PBCHANNEL_OBJECT pBChannel // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call manager maintains its per-VC state. The call manager supplied
|
|
// this handle from its <f ProtocolCoCreateVc> function.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmDeactivateVcComplete")
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState, Status
|
|
));
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCmModifyCallQoS
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCmModifyCallQoS> is a required function that is called by NDIS
|
|
when a connection-oriented client requests that the call parameters be
|
|
changed for an existing virtual connection (VC). If the underlying network
|
|
medium does not support QoS, ProtocolCmModifyQoS should simply return
|
|
NDIS_STATUS_NOT_SUPPORTED.
|
|
|
|
@comm
|
|
|
|
ProtocolCmModifyQoS communicates with network control devices or other
|
|
media-specific agents, as necessitated by its media, to modify the
|
|
media-specific call parameters for an established virtual connection. If the
|
|
call manager is required to communicate with network control agents (e.g. a
|
|
networking switch) it should use a virtual connection to the network control
|
|
agents that it established in its ProtocolBindAdapter function. Standalone
|
|
call managers communicated to the network agents by calling
|
|
NdisCoSendPackets. NIC miniports with integrated call-management support
|
|
never call NdisCoSendPackets. Instead, such a driver simply transfers the
|
|
data over the network to the target network agent.
|
|
|
|
After communicating with the network and if the changes were successful, the
|
|
call manager must then call NdisCmActivateVc with the new call parameters.
|
|
This notifies NDIS and/or the connection-oriented miniport that the call
|
|
parameters have changed and provides the miniport with an opportunity to
|
|
validate those parameters.
|
|
|
|
If either the network cannot accept the new call parameters or the
|
|
underlying miniport cannot accept the parameters, the call manager must
|
|
restore the virtual connection to the state that existed before any
|
|
modifications were attempted, and return NDIS_STATUS_FAILURE.
|
|
|
|
ProtocolCmModifyQoSComplete must be written so that it can run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCmModifyQoS returns the status of its operation(s) as one of the
|
|
following values:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
Indicates that the call manager successfully changed the parameters of the
|
|
call with the network to the call parameters specified at CallParameters.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
Indicates that the call manager will complete the request to modify the call
|
|
parameters asynchronously. When the call manager has completed all
|
|
operations necessary to modify the call parameters, it must call
|
|
NdisCmModifyCallQoSComplete.
|
|
|
|
@rvalue NDIS_STATUS_RESOURCES |
|
|
|
|
Indicates that the call manager could not change the call parameters of the
|
|
VC because dynamically allocated resources were not available.
|
|
|
|
@rvalue NDIS_STATUS_INVALID_DATA |
|
|
|
|
Indicates that the call manager was unable to change the call parameters of
|
|
the VC because the call parameters provided at CallParameters were illegal
|
|
or invalid.
|
|
|
|
@rvalue NDIS_STATUS_FAILURE |
|
|
|
|
Indicates that the call parameters could not be set to the call parameters
|
|
provided because of a failure in the network or in another
|
|
connection-oriented network component.
|
|
|
|
|
|
@xref
|
|
|
|
NdisCmActivateVc, NdisCmModifyCallQoSComplete, NdisCoSendPackets,
|
|
<f ProtocolCoCreateVc>
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCmModifyCallQoS(
|
|
IN PBCHANNEL_OBJECT pBChannel, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCmMakeCall>. AKA CallMgrVcContext.<nl>
|
|
// Specifies the handle to a call manager-allocated context area in which
|
|
// the call manager maintains its per-VC state. The call manager supplied
|
|
// this handle from its <f ProtocolCoCreateVc> function.
|
|
|
|
IN PCO_CALL_PARAMETERS pCallParameters // @parm
|
|
// Points to a CO_CALL_PARAMETERS structure that contains the new call
|
|
// parameters, as specified by a connection-oriented client, for the VC.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmModifyCallQoS")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = pBChannel->pAdapter;
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState
|
|
));
|
|
|
|
// What do you want to do with this request?
|
|
DBG_ERROR(pAdapter, ("pCallParameters=0x%X\n", pCallParameters));
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCoRequest
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCoRequest> is a required function that handles OID_CO_XXX
|
|
requests initiated by calls to NdisCoRequest from the corresponding
|
|
client(s) or stand-alone call manager or initiated by an MCM driver's calls
|
|
to NdisMCmRequest.
|
|
|
|
@comm
|
|
|
|
Connection-oriented clients and stand-alone call managers communicate
|
|
information to each other by specifying an explicit NdisAfHandle when they
|
|
call NdisCoRequest. Similarly, a connection-oriented miniport with
|
|
integrated call-management support calls NdisMCmRequest with explicit
|
|
NdisAfHandles to communicate information to its individual clients. Such a
|
|
call to NdisCoRequest or NdisMCmRequest with an explicit NdisAfHandle causes
|
|
NDIS to call the ProtocolCoRequest function of the client, stand-alone call
|
|
manager, or MCM driver that shares the given NdisAfHandle.
|
|
|
|
If the input NdisVcHandle and NdisPartyHandle are NULL, ProtocolCoRequest
|
|
can consider the request global in nature. For example, ProtocolCoRequest
|
|
satisfies any OID_GEN_CO_XXX query for which it is passed only an explicit
|
|
NdisAfHandle by returning information about all currently active VCs,
|
|
including any active multipoint VCs, on the given address family.
|
|
|
|
An explicit NdisVcHandle or NdisPartyHandle indicates that ProtocolCoRequest
|
|
should satisfy the given request on a per-VC or per-party basis,
|
|
respectively.
|
|
|
|
ProtocolCoRequest can assume that the buffer at NdisRequest was allocated
|
|
from nonpaged pool and is, therefore, accessible at raised IRQL. The caller
|
|
of NdisCoRequest (or NdisMCmRequest) is responsible for releasing this
|
|
buffer and the internal buffer at InformationBuffer that it allocated when
|
|
its request has been completed.
|
|
|
|
If ProtocolCoRequest returns NDIS_STATUS_PENDING, the driver must make a
|
|
subsequent call to NdisCoRequestComplete or, for an MCM driver, to
|
|
NdisMCmRequestComplete when the driver completes its operations to satisfy
|
|
the given request.
|
|
|
|
For more information about the sets of OIDs defined for use with
|
|
NdisCoRequest, NdisMCmRequest, and NdisRequest, see Part 2 of this manual.
|
|
|
|
ProtocolCoRequest must be written so that it can run at IRQL DISPATCH_LEVEL.
|
|
|
|
@rdesc
|
|
|
|
ProtocolCoRequest can return one of the following:
|
|
|
|
@rvalue NDIS_STATUS_SUCCESS |
|
|
|
|
The client or call manager carried out the requested operation.
|
|
|
|
@rvalue NDIS_STATUS_PENDING |
|
|
|
|
The client or call manager is handling this request asynchronously, and it
|
|
will call NdisCoRequestComplete (or, from a NIC miniport with integrated
|
|
call-management support, NdisMCmRequestComplete) when the requested
|
|
operation is done.
|
|
|
|
@rvalue NDIS_STATUS_INVALID_LENGTH or NDIS_STATUS_BUFFER_TOO_SHORT |
|
|
|
|
The driver is failing this request because the caller of NdisCoRequest or
|
|
NdisMCmRequest did not supply an adequate InformationBuffer for the given
|
|
request. The driver set the BytesNeeded member in the buffer at NdisRequest
|
|
to the Oid-specific value of the InformationBufferLength required to carry
|
|
out the requested operation.
|
|
|
|
@rvalue NDIS_STATUS_XXX |
|
|
|
|
The client or call manager failed the request for some driver-determined
|
|
reason, such as invalid input data specified for a set.
|
|
|
|
@rvalue NDIS_STATUS_NOT_SUPPORTED |
|
|
|
|
The client or call manager failed this request because it did not recognize
|
|
the OID_GEN_CO_XXX code in the Oid member in the buffer at NdisRequest.
|
|
|
|
@xref
|
|
|
|
NdisClOpenAddressFamily, NdisCoRequest, NdisCoRequestComplete,
|
|
NdisMCmRequest, NdisMCmRequestComplete, NdisRequest, NDIS_REQUEST,
|
|
ProtocolCmOpenAf, ProtocolCoRequestComplete
|
|
|
|
*/
|
|
|
|
NDIS_STATUS ProtocolCoRequest(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>. AKA ProtocolAfContext.<nl>
|
|
// Specifies the handle to the driver's per-AF context area. The client
|
|
// supplied this handle when it called NdisClOpenAddressFamily to connect
|
|
// itself to the call manager. The call manager supplied this handle from
|
|
// its <f ProtocolCmOpenAf> function, so this handle effectively identifies
|
|
// the particular client that issued this request.
|
|
|
|
IN PBCHANNEL_OBJECT pBChannel OPTIONAL, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f BChannelCreate>. AKA ProtocolVcContext.<nl>
|
|
// Specifies the handle identifying the active VC for which the client or
|
|
// call manager is requesting or setting information if the request is
|
|
// VC-specific. Otherwise, this parameter is NULL.
|
|
|
|
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, // @parm
|
|
// Specifies the handle identifying the party on a multipoint VC for which
|
|
// the client or call manager is requesting or setting information if the
|
|
// request is party-specific. Otherwise, this parameter is NULL.
|
|
|
|
IN OUT PNDIS_REQUEST NdisRequest
|
|
// Points to a buffer, formatted as an NDIS_REQUEST structure specifying
|
|
// the operation to be carried out by ProtocolCoRequest. The Oid member of
|
|
// the NDIS_REQUEST structure contains the system-defined OID_GEN_CO_XXX
|
|
// code specifying the requested query or set operation, together with a
|
|
// buffer in which the protocol returns the requested information for a
|
|
// query or from which it transfers the given information for a set.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmRequest")
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
// ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
Result = MiniportCoRequest(pAdapter, pBChannel, NdisRequest);
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc EXTERNAL INTERNAL CallMgr CallMgr_c ProtocolCoRequestComplete
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ProtocolCoRequestComplete> is a required function that postprocesses the
|
|
results of a connection-oriented client's or stand-alone call manager's call
|
|
to NdisCoRequest or of an MCM driver's call to NdisMCmRequest.
|
|
|
|
@comm
|
|
|
|
ProtocolCoRequestComplete can use the input Status as follows:
|
|
|
|
If this argument is NDIS_STATUS_SUCCESS, the BytesRead or BytesWritten
|
|
member of the NDIS_REQUEST structure has been set to specify how much data
|
|
was transferred into or from the buffer at InformationBuffer.
|
|
|
|
If the given OID_GEN_CO_XXX was a query, ProtocolCoRequestComplete can use
|
|
the data returned at InformationBuffer in any driver-determined way,
|
|
depending on the value of the Oid member.
|
|
|
|
ProtocolCoRequestComplete is responsible for releasing the driver-allocated
|
|
buffers at NdisRequest and InformationBuffer when the driver completes its
|
|
postprocessing of this request.
|
|
|
|
If this argument is NDIS_STATUS_INVALID_LENGTH or
|
|
NDIS_STATUS_BUFFER_TOO_SHORT, the BytesNeeded member specifies the
|
|
Oid-specific value of the InformationBufferLength required to carry out the
|
|
requested operation.
|
|
|
|
In these circumstances, ProtocolCoRequestComplete can allocate sufficient
|
|
buffer space for the request, set up another NDIS_REQUEST structure with the
|
|
required InformationBufferLength and the same Oid value, and retry the
|
|
driver's call to NdisCoRequest or NdisMCmRequest.
|
|
|
|
If this argument is an NDIS_STATUS_XXX that indicates an unrecoverable
|
|
error, ProtocolCoRequestComplete should release the buffer at NdisRequest
|
|
and carry out any driver-determined operations that are necessary. For
|
|
example, ProtocolCoRequestComplete might tear down the driver-created VC if
|
|
a returned error status indicates that the driver cannot continue to make
|
|
transfers on the virtual connection.
|
|
|
|
Even if a driver's call to NdisCoRequest or NdisMCmRequest returns something
|
|
other than NDIS_STATUS_PENDING, that driver should use its
|
|
ProtocolCoRequestComplete function to postprocess completed requests. Making
|
|
an internal call to the driver's own ProtocolCoRequestComplete function on
|
|
return from NdisCoRequest or NdisMCmRequest has almost no adverse effect on
|
|
the driver's performance, makes the driver's image smaller, and makes the
|
|
driver easier to maintain from one OS release to the next since such a
|
|
driver has no duplicate code doing status-return checking on
|
|
driver-initiated requests.
|
|
|
|
For more information about the sets of OIDs defined for use with
|
|
NdisCoRequest and NdisMCmRequest, see Part 2 of this manual.
|
|
|
|
ProtocolCoRequestComplete must be written so that it can run at IRQL
|
|
DISPATCH_LEVEL.
|
|
|
|
@xref
|
|
|
|
NdisCoRequest, NdisCoRequestComplete, NdisMCmRequest,
|
|
NdisMCmRequestComplete, NDIS_REQUEST, <f ProtocolCoRequest>
|
|
|
|
*/
|
|
|
|
VOID ProtocolCoRequestComplete(
|
|
IN NDIS_STATUS Status, // @parm
|
|
// Specifies the final status of the driver-initiated request, either
|
|
// NDIS_STATUS_SUCCESS or a failure NDIS_STATUS_XXX that was set by the
|
|
// corresponding client or call manager that handled this request. This
|
|
// parameter is never NDIS_STATUS_PENDING.
|
|
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>. AKA ProtocolAfContext.<nl>
|
|
// Specifies the handle to the driver's per-AF context area. The client
|
|
// supplied this handle when it called NdisClOpenAddressFamily to connect
|
|
// itself to the call manager. The call manager supplied this handle from
|
|
// its ProtocolCmOpenAf function, so this handle effectively identifies the
|
|
// particular client to which this request was directed.
|
|
|
|
IN PBCHANNEL_OBJECT pBChannel OPTIONAL, // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f BChannelCreate>. AKA ProtocolVcContext.<nl>
|
|
// Specifies the handle identifying the active VC for which the client or
|
|
// call manager was requesting or setting information if the request was
|
|
// VC-specific. Otherwise, this parameter is NULL.
|
|
|
|
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, // @parm
|
|
// Specifies the handle identifying the party on a multipoint VC for which
|
|
// the client or call manager was requesting or setting information if the
|
|
// request is party-specific. Otherwise, this parameter is NULL.
|
|
|
|
IN PNDIS_REQUEST NdisRequest // @parm
|
|
// Points to the driver-allocated buffer, formatted as an NDIS_REQUEST
|
|
// structure that the driver passed in a preceding call to NdisCoRequest or
|
|
// NdisMCmRequest. The Oid member of the NDIS_REQUEST structure contains
|
|
// the system-defined OID_GEN_CO_XXX code specifying the requested query or
|
|
// set operation, together with a buffer in which the corresponding client
|
|
// or call manager returned the requested information for a query or from
|
|
// which it transferred the given information for a set if Status is
|
|
// NDIS_STATUS_SUCCESS.
|
|
)
|
|
{
|
|
DBG_FUNC("ProtocolCmRequestComplete")
|
|
|
|
// ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState, Status
|
|
));
|
|
|
|
// MCM's don't typically need this, since there's nothing below...
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c AllocateIncomingCallParameters
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f AllocateIncomingCallParameters> is called by <f SetupIncomingCall>
|
|
when getting ready to indicate an incoming call up to NDPROXY.
|
|
|
|
@comm
|
|
|
|
AllocateIncomingCallParameters allocates memory for the incoming call
|
|
parameters <t PCO_CALL_PARAMETERS>. The memory is only allocated the
|
|
first time a call comes in on a particular BChannel. After that, the
|
|
same structure is reused for each incoming call on that BChannel.
|
|
|
|
The structure is defined by NDPROXY, CONDIS, and TAPI so it includes
|
|
all the necessary media specific parameters. The data structures are
|
|
allocated and laid out end to end in the following format:
|
|
|
|
<tab> sizeof(CO_CALL_PARAMETERS)<nl>
|
|
<tab> sizeof(CO_CALL_MANAGER_PARAMETERS)<nl>
|
|
<tab> sizeof(CO_MEDIA_PARAMETERS)<nl>
|
|
<tab> sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)<nl>
|
|
<tab> sizeof(LINE_CALL_INFO)<nl>
|
|
|
|
The call parameters for the sample driver are hard coded, but you should
|
|
fill in the correct information from incoming call request.
|
|
|
|
*/
|
|
|
|
PCO_CALL_PARAMETERS AllocateIncomingCallParameters(
|
|
IN PBCHANNEL_OBJECT pBChannel // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>.
|
|
)
|
|
{
|
|
DBG_FUNC("AllocateIncomingCallParameters")
|
|
|
|
PCO_CALL_PARAMETERS pCp;
|
|
PCO_CALL_MANAGER_PARAMETERS pCmp;
|
|
PCO_MEDIA_PARAMETERS pMp;
|
|
PCO_AF_TAPI_INCOMING_CALL_PARAMETERS pTcp;
|
|
PLINE_CALL_INFO pLci;
|
|
|
|
NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
|
|
// Holds the result code returned by this function.
|
|
|
|
PMINIPORT_ADAPTER_OBJECT pAdapter;
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
|
|
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
ASSERT(pBChannel->NdisTapiSap.ulMediaModes & LINEMEDIAMODE_DIGITALDATA);
|
|
pBChannel->MediaMode = LINEMEDIAMODE_DIGITALDATA;
|
|
pBChannel->BearerMode = LINEBEARERMODE_DATA;
|
|
pBChannel->LinkSpeed = _64KBPS;
|
|
|
|
if (pBChannel->pInCallParms != NULL)
|
|
{
|
|
// Already allocated call parameters for this channel.
|
|
return (pBChannel->pInCallParms);
|
|
}
|
|
|
|
pBChannel->CallParmsSize = sizeof(CO_CALL_PARAMETERS)
|
|
+ sizeof(CO_CALL_MANAGER_PARAMETERS)
|
|
+ sizeof(CO_MEDIA_PARAMETERS)
|
|
+ sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)
|
|
+ sizeof(LINE_CALL_INFO);
|
|
|
|
ALLOCATE_MEMORY(pBChannel->pInCallParms,
|
|
pBChannel->CallParmsSize,
|
|
pAdapter->MiniportAdapterHandle);
|
|
|
|
if (pBChannel->pInCallParms == NULL)
|
|
{
|
|
return (pBChannel->pInCallParms);
|
|
}
|
|
|
|
NdisZeroMemory(pBChannel->pInCallParms, pBChannel->CallParmsSize);
|
|
|
|
DBG_NOTICE(pAdapter,(
|
|
"\n"
|
|
"\t\tsizeof(CO_CALL_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(CO_CALL_MANAGER_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(CO_MEDIA_PARAMETERS) =%03d\n"
|
|
"\t\tsizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)=%03d\n"
|
|
"\t\tsizeof(LINE_CALL_INFO) =%03d\n"
|
|
"\t\tTotal =%03d\n",
|
|
sizeof(CO_CALL_PARAMETERS),
|
|
sizeof(CO_CALL_MANAGER_PARAMETERS),
|
|
sizeof(CO_MEDIA_PARAMETERS),
|
|
sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS),
|
|
sizeof(LINE_CALL_INFO),
|
|
pBChannel->CallParmsSize
|
|
));
|
|
pCp = (PCO_CALL_PARAMETERS) pBChannel->pInCallParms;
|
|
pCmp = (PCO_CALL_MANAGER_PARAMETERS)(pCp + 1);
|
|
pMp = (PCO_MEDIA_PARAMETERS) (pCmp + 1);
|
|
pTcp = (PCO_AF_TAPI_INCOMING_CALL_PARAMETERS)
|
|
pMp->MediaSpecific.Parameters;
|
|
pLci = (PLINE_CALL_INFO) (pTcp + 1);
|
|
|
|
// TODO: Fill in the call parameters as needed.
|
|
|
|
pCp->Flags = PERMANENT_VC;
|
|
pCp->CallMgrParameters = pCmp;
|
|
pCp->MediaParameters = pMp;
|
|
|
|
pCmp->Transmit.TokenRate = pBChannel->LinkSpeed / 8;
|
|
pCmp->Transmit.TokenBucketSize = pAdapter->pCard->BufferSize;
|
|
pCmp->Transmit.PeakBandwidth = pBChannel->LinkSpeed / 8;
|
|
pCmp->Transmit.Latency = 0;
|
|
pCmp->Transmit.DelayVariation = 0;
|
|
pCmp->Transmit.ServiceType = SERVICETYPE_BESTEFFORT;
|
|
pCmp->Transmit.MaxSduSize = pAdapter->pCard->BufferSize;
|
|
pCmp->Transmit.MinimumPolicedSize = 0;
|
|
pCmp->Receive = pCmp->Transmit;
|
|
pCmp->CallMgrSpecific.ParamType = 0;
|
|
pCmp->CallMgrSpecific.Length = 0;
|
|
|
|
pMp->Flags = TRANSMIT_VC | RECEIVE_VC;
|
|
pMp->ReceiveSizeHint = pAdapter->pCard->BufferSize;
|
|
pMp->MediaSpecific.ParamType = 0;
|
|
pMp->MediaSpecific.Length = sizeof(*pTcp) + sizeof(*pLci);
|
|
|
|
pTcp->ulLineID = pBChannel->NdisTapiSap.ulLineID;
|
|
pTcp->ulAddressID = TSPI_ADDRESS_ID;
|
|
pTcp->ulFlags = CO_TAPI_FLAG_INCOMING_CALL;
|
|
pTcp->LineCallInfo.Length = sizeof(*pLci);
|
|
pTcp->LineCallInfo.MaximumLength = sizeof(*pLci);
|
|
pTcp->LineCallInfo.Offset = sizeof(NDIS_VAR_DATA_DESC);
|
|
|
|
pLci->ulTotalSize =
|
|
pLci->ulNeededSize =
|
|
pLci->ulUsedSize = sizeof(*pLci);
|
|
|
|
/*
|
|
// The link has all the call information we need to return.
|
|
*/
|
|
pLci->hLine = (ULONG) (ULONG_PTR) pBChannel;
|
|
pLci->ulLineDeviceID = pTcp->ulLineID;
|
|
pLci->ulAddressID = pTcp->ulAddressID;
|
|
|
|
pLci->ulBearerMode = pBChannel->BearerMode;
|
|
pLci->ulRate = pBChannel->LinkSpeed;
|
|
pLci->ulMediaMode = pBChannel->MediaMode;
|
|
|
|
pLci->ulCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
|
pLci->ulCallStates = pBChannel->CallStatesCaps;
|
|
|
|
/*
|
|
// We don't support any of the callerid functions.
|
|
*/
|
|
pLci->ulCallerIDFlags =
|
|
pLci->ulCalledIDFlags =
|
|
pLci->ulConnectedIDFlags =
|
|
pLci->ulRedirectionIDFlags =
|
|
pLci->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
|
|
DBG_RETURN(pAdapter, pBChannel->pInCallParms);
|
|
return (pBChannel->pInCallParms);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c SetupIncomingCall
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f SetupIncomingCall> is called by the card level DPC routine when it
|
|
detects an incoming call from the network.
|
|
|
|
@comm
|
|
|
|
Before calling this routine, the caller should save information about
|
|
the call so it can be used by <f AllocateIncomingCallParameters> to
|
|
setup the incoming call parameters for NDPROXY.
|
|
|
|
@rdesc
|
|
|
|
<f SetupIncomingCall> returns zero if it is successful.<nl>
|
|
Otherwise, a non-zero return value indicates an error condition.
|
|
|
|
*/
|
|
|
|
NDIS_STATUS SetupIncomingCall(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>.
|
|
|
|
OUT PBCHANNEL_OBJECT * ppBChannel // @parm
|
|
// Specifies, on output, a pointer to the <t BCHANNEL_OBJECT> instance
|
|
// returned by <f ProtocolCoCreateVc> that is to be associated with this
|
|
// incoming call.
|
|
)
|
|
{
|
|
DBG_FUNC("SetupIncomingCall")
|
|
|
|
NDIS_STATUS Result;
|
|
// Holds the result code returned by this function.
|
|
|
|
PCO_CALL_PARAMETERS pCallParams;
|
|
// Pointer to the incoming call parameters.
|
|
|
|
PBCHANNEL_OBJECT pBChannel;
|
|
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
// See if there's a VC availble for this call.
|
|
Result = ProtocolCoCreateVc(pAdapter, NULL, ppBChannel);
|
|
if (Result != NDIS_STATUS_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Save the VC info and allocate the call parameters.
|
|
pBChannel = *ppBChannel;
|
|
pBChannel->Flags |= VCF_INCOMING_CALL;
|
|
pCallParams = AllocateIncomingCallParameters(pBChannel);
|
|
|
|
// Make sure we have the parameters
|
|
if (pCallParams == NULL)
|
|
{
|
|
Result = NDIS_STATUS_RESOURCES;
|
|
goto error2;
|
|
}
|
|
|
|
// Tell NDPROXY to create a VC for this call.
|
|
Result = NdisMCmCreateVc(pAdapter->MiniportAdapterHandle,
|
|
pAdapter->NdisAfHandle,
|
|
pBChannel,
|
|
&pBChannel->NdisVcHandle);
|
|
if (Result != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBG_ERROR(pAdapter, ("NdisMCmCreateVc Status=0x%X\n", Result));
|
|
goto error2;
|
|
}
|
|
|
|
// Tell NDPROXY to activate the VC.
|
|
Result = NdisMCmActivateVc(pBChannel->NdisVcHandle, pCallParams);
|
|
if (Result != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBG_ERROR(pAdapter, ("NdisMCmActivateVc Status=0x%X\n", Result));
|
|
goto error3;
|
|
}
|
|
|
|
// Mark the VC as active and update the call state.
|
|
pBChannel->Flags |= VCF_VC_ACTIVE;
|
|
pBChannel->CallState = LINECALLSTATE_OFFERING;
|
|
|
|
DBG_FILTER(pAdapter,DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X AF=0x%X SAP=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle,
|
|
pAdapter->NdisAfHandle, pBChannel->NdisSapHandle
|
|
));
|
|
|
|
// Tell NDPROXY to dispatch the call to the TAPI clients.
|
|
Result = NdisMCmDispatchIncomingCall(pBChannel->NdisSapHandle,
|
|
pBChannel->NdisVcHandle,
|
|
pCallParams);
|
|
switch (Result)
|
|
{
|
|
case NDIS_STATUS_SUCCESS:
|
|
DBG_NOTICE(pAdapter,("NdisMCmDispatchIncomingCall completed synchronously\n"));
|
|
ProtocolCmIncomingCallComplete(Result, pBChannel, NULL);
|
|
goto exit;
|
|
|
|
case NDIS_STATUS_PENDING:
|
|
DBG_NOTICE(pAdapter,("NdisMCmDispatchIncomingCall returned pending\n"));
|
|
// Let ProtocolCmIncomingCallComplete deal with it now.
|
|
goto exit;
|
|
}
|
|
|
|
// BUMMER - There must be a problem with NDPRROXY...
|
|
DBG_ERROR(pAdapter, ("NdisMCmDispatchIncomingCall Status=0x%X\n", Result));
|
|
|
|
pBChannel->CallState = LINECALLSTATE_IDLE;
|
|
if (pBChannel->Flags & VCF_VC_ACTIVE)
|
|
{
|
|
pBChannel->Flags &= ~VCF_VC_ACTIVE;
|
|
NdisMCmDeactivateVc(pBChannel->NdisVcHandle);
|
|
}
|
|
|
|
error3:
|
|
if (pBChannel->NdisVcHandle)
|
|
{
|
|
NdisMCmDeleteVc(pBChannel->NdisVcHandle);
|
|
pBChannel->NdisVcHandle = NULL;
|
|
}
|
|
|
|
error2:
|
|
ProtocolCoDeleteVc((NDIS_HANDLE) pBChannel);
|
|
|
|
exit:
|
|
|
|
DBG_RETURN(pAdapter, Result);
|
|
return (Result);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL CallMgr CallMgr_c InitiateCallTeardown
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f InitiateCallTeardown> is called by the card level DPC routine when it
|
|
detects a call disconnect from the network.
|
|
|
|
@comm
|
|
|
|
The disconnect here is coming from the telephone network rather than from
|
|
NDIS. This can be called on either an incoming call or an outgoing call
|
|
when the miniport has determined that the link has been lost to the remote
|
|
endpoint.
|
|
|
|
*/
|
|
|
|
VOID InitiateCallTeardown(
|
|
IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
|
|
// A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
|
|
// <f AdapterCreate>.
|
|
|
|
IN PBCHANNEL_OBJECT pBChannel // @parm
|
|
// A pointer to the <t BCHANNEL_OBJECT> instance returned by
|
|
// <f ProtocolCoCreateVc>.
|
|
)
|
|
{
|
|
DBG_FUNC("InitiateCallTeardown")
|
|
|
|
NDIS_STATUS Status;
|
|
|
|
ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
|
|
ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
|
|
|
|
DBG_ENTER(pAdapter);
|
|
|
|
if (pBChannel->Flags & VCF_VC_ACTIVE)
|
|
{
|
|
// Normal teardown.
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// Call never fully established.
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
DBG_FILTER(pAdapter, DBG_TAPICALL_ON,
|
|
("#%d VC=0x%X CallState=0x%X Status=0x%X\n",
|
|
pBChannel->ObjectID,
|
|
pBChannel->NdisVcHandle, pBChannel->CallState,
|
|
Status
|
|
));
|
|
|
|
pBChannel->CallState = LINECALLSTATE_DISCONNECTED;
|
|
|
|
// Make sure there are no packets left on this channel before it closes.
|
|
FlushSendPackets(pAdapter, pBChannel);
|
|
|
|
// Notify NDPROXY that the call's connection has been lost.
|
|
NdisMCmDispatchIncomingCloseCall(Status,
|
|
pBChannel->NdisVcHandle,
|
|
NULL, 0);
|
|
|
|
DBG_LEAVE(pAdapter);
|
|
}
|
|
|