windows-nt/Source/XPSP1/NT/net/rras/ndis/ndproxy/pxtapi.c

5205 lines
134 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
pxtapi.c
Abstract:
The module contains the TAPI-specific code for the NDIS Proxy.
Author:
Richard Machin (RMachin)
Revision History:
Who When What
-------- -------- ----------------------------------------------
RMachin 01-08-97 created (after Dan Knudson's NdisTapi)
TonyBe 02-21-99 re-work/re-write
Notes:
--*/
#include <precomp.h>
#include <stdio.h>
#define MODULE_NUMBER MODULE_TAPI
#define _FILENUMBER 'IPAT'
ULONG
GetLineEvents(
PCHAR EventBuffer,
ULONG BufferSize
)
/*++
Routine Description:
Gets event data out of our global event queue and writes it to the buffer. Data is put into the queue
by PxIndicateStatus (above).
Arguments:
EventBuffer pointer to a buffer of size BufferSize
BufferSize size of event buffer (expected to be 1024)
Return Value:
Note:
Assumes TspEventList.Lock held by caller.
--*/
{
ULONG BytesLeft;
ULONG BytesMoved = 0;
BytesLeft = BufferSize;
while (!(IsListEmpty(&TspEventList.List))) {
PPROVIDER_EVENT ProviderEvent;
if (BytesLeft < sizeof(NDIS_TAPI_EVENT)) {
break;
}
ProviderEvent = (PPROVIDER_EVENT)
RemoveHeadList(&TspEventList.List);
TspEventList.Count--;
RtlMoveMemory(EventBuffer + BytesMoved,
(PUCHAR)&ProviderEvent->Event,
sizeof(NDIS_TAPI_EVENT));
BytesMoved += sizeof(NDIS_TAPI_EVENT);
BytesLeft -= sizeof(NDIS_TAPI_EVENT);
ExFreeToNPagedLookasideList(&ProviderEventLookaside,
ProviderEvent);
}
return (BytesMoved);
}
NDIS_STATUS
PxTapiMakeCall(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TSPI_lineMakeCall handler.
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_MAKE_CALL TapiBuffer =
(PNDIS_TAPI_MAKE_CALL)(pNdisTapiRequest->Data);
LINE_CALL_PARAMS* pTapiCallParams =
(LINE_CALL_PARAMS*)(&TapiBuffer->LineCallParams);
PPX_TAPI_LINE TapiLine;
PPX_TAPI_ADDR TapiAddr;
PPX_VC pVc = NULL;
PPX_CL_AF pClAf;
PCO_CALL_PARAMETERS pNdisCallParams = 0;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG targetDeviceID = 0;
LPCWSTR lpcwszTemp;
PPX_ADAPTER pAdapter;
PPX_TAPI_PROVIDER TapiProvider;
lpcwszTemp = (LPWSTR)
(((UCHAR *) TapiBuffer) + TapiBuffer->ulDestAddressOffset);
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("TapiMakeCall: DialAddress in Tapi buffer %x = %ls\n",lpcwszTemp, lpcwszTemp));
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
PXDEBUGP (PXD_WARNING, PXM_TAPI,
("PxTapiMakeCall: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
return (NDISTAPIERR_BADDEVICEID);
}
do {
NdisAcquireSpinLock(&TapiLine->Lock);
//
// Is this line in service? (does it have an valid af?)
//
if (!(TapiLine->DevStatus->ulDevStatusFlags &
LINEDEVSTATUSFLAGS_INSERVICE)) {
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiMakeCall: Line not in service!\n"));
NdisReleaseSpinLock(&TapiLine->Lock);
Status = NDISTAPIERR_DEVICEOFFLINE;
break;
}
PXDEBUGP (PXD_TAPI, PXM_TAPI,
("PxTapiMakeCall: got device x%x from ID %d\n", TapiLine, TapiBuffer->hdLine));
if (pTapiCallParams->ulAddressMode == LINEADDRESSMODE_ADDRESSID) {
//
// Get the specificed address from the address id
//
if (!IsAddressValid(TapiLine, pTapiCallParams->ulAddressID, &TapiAddr)) {
Status = NDISTAPIERR_BADDEVICEID;
NdisReleaseSpinLock(&TapiLine->Lock);
break;
}
} else {
//
// Get the first available address
//
TapiAddr =
GetAvailAddrFromLine(TapiLine);
if (TapiAddr == NULL) {
Status = NDISTAPIERR_BADDEVICEID;
NdisReleaseSpinLock(&TapiLine->Lock);
break;
}
}
TapiProvider = TapiLine->TapiProvider;
pAdapter = TapiProvider->Adapter;
pClAf = TapiLine->ClAf;
NdisReleaseSpinLock(&TapiLine->Lock);
NdisAcquireSpinLock(&pClAf->Lock);
//
// Allocate a Vc block. This will create the block
// with refcount = 1.
//
pVc = PxAllocateVc(pClAf);
if (pVc == NULL) {
PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiMakeCall: failed to allocate a vc\n"));
NdisReleaseSpinLock(&pClAf->Lock);
Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
break;
}
NdisReleaseSpinLock(&pClAf->Lock);
Status =
AllocateTapiCallInfo(pVc, NULL);
if (Status != NDIS_STATUS_SUCCESS) {
PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiMakeCall: Error allocating TapiCallInfo!\n"));
PxFreeVc(pVc);
Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
break;
}
pVc->TapiLine = TapiLine;
pVc->TapiAddr = TapiAddr;
InterlockedIncrement((PLONG)&TapiAddr->CallCount);
InterlockedIncrement((PLONG)&TapiLine->DevStatus->ulNumActiveCalls);
pVc->htCall = TapiBuffer->htCall;
pVc->CallInfo->ulLineDeviceID = TapiLine->CmLineID;
pVc->CallInfo->ulAddressID = TapiAddr->AddrId;
pVc->CallInfo->ulOrigin = LINECALLORIGIN_OUTBOUND;
//
// Set up intended bearer and media mode
//
pVc->CallInfo->ulBearerMode =
pTapiCallParams->ulBearerMode;
pVc->CallInfo->ulMediaMode =
pTapiCallParams->ulMediaMode;
if (pTapiCallParams->ulMaxRate == 0) {
pVc->CallInfo->ulRate =
TapiLine->DevCaps->ulMaxRate;
} else {
pVc->CallInfo->ulRate =
pTapiCallParams->ulMaxRate;
}
if (!InsertVcInTable(pVc)) {
PXDEBUGP (PXD_WARNING, PXM_TAPI,
("PxTapiMakeCall: failed to insert in vc table\n"));
PxFreeVc(pVc);
Status = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
break;
}
//
// Our call handle is an index into the call table
//
TapiBuffer->hdCall = (HDRV_CALL)pVc->hdCall;
Status = NdisCoCreateVc(pAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
(NDIS_HANDLE)pVc->hdCall,
&pVc->ClVcHandle);
if (Status != NDIS_STATUS_SUCCESS) {
RemoveVcFromTable(pVc);
PxFreeVc(pVc);
Status = NDIS_STATUS_TAPI_CALLUNAVAIL;
break;
}
//
// Move (AF-specific) call parameters into NdisCallParams structure
//
Status =
(*pClAf->AfGetNdisCallParams)(pVc,
TapiLine->CmLineID,
TapiAddr->AddrId,
CO_TAPI_FLAG_OUTGOING_CALL,
TapiBuffer,
&pNdisCallParams);
if (Status != NDIS_STATUS_SUCCESS) {
PXDEBUGP (PXD_WARNING, PXM_TAPI,
("PxTapiMakeCall: failed to move call params: Status %x\n", Status));
NdisCoDeleteVc(pVc->ClVcHandle);
RemoveVcFromTable(pVc);
PxFreeVc(pVc);
Status = NDIS_STATUS_TAPI_INVALCALLPARAMS;
break;
}
// Store Call Params for when lineGetID dispatches an incoming call...
//
NdisAcquireSpinLock(&pVc->Lock);
pVc->pCallParameters = pNdisCallParams;
pVc->PrevState = pVc->State;
pVc->State = PX_VC_PROCEEDING;
pVc->Flags |= PX_VC_OWNER;
//
// Ref applied ndis part of the make call.
// This ref is removed in PxClCloseCallComplete or
// PxClMakeCallComplete in the case of a make call
// failure.
//
REF_VC(pVc);
//
// Indicate call state change to TAPI
//
SendTapiCallState(pVc,
LINECALLSTATE_PROCEEDING,
0,
pVc->CallInfo->ulMediaMode);
NdisReleaseSpinLock(&pVc->Lock);
Status =
NdisClMakeCall(pVc->ClVcHandle,
pVc->pCallParameters,
NULL,
NULL);
if (Status != NDIS_STATUS_PENDING) {
PxClMakeCallComplete(Status,
(NDIS_HANDLE)pVc->hdCall,
NULL,
pVc->pCallParameters);
}
Status = NDIS_STATUS_SUCCESS;
} // end of do loop
while (FALSE);
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiMakeCall: exit Status %x\n", Status));
DEREF_TAPILINE(TapiLine);
return Status;
}
NDIS_STATUS
PxTapiGetDevCaps(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Stick the appropriate device info into the request buffer.
Arguments:
Request -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PPX_TAPI_LINE TapiLine = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps =
(PNDIS_TAPI_GET_DEV_CAPS) pNdisTapiRequest->Data;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevCaps: enter\n"));
if (!IsTapiDeviceValid(pNdisTapiGetDevCaps->ulDeviceID, &TapiLine)) {
PXDEBUGP (PXD_WARNING, PXM_TAPI,
( "PxTapiGetDevCaps: NDISTAPIERR_BADDEVICEID: line = %x\n",
pNdisTapiGetDevCaps->ulDeviceID));
return(NDISTAPIERR_BADDEVICEID);
}
NdisAcquireSpinLock(&TapiLine->Lock);
do {
ULONG SizeDevCaps;
ULONG DevClassesSize = 0;
USHORT DevClassesList[512];
WCHAR LineName[128];
ULONG LineNameSize;
WCHAR ProviderInfo[128];
ULONG ProviderInfoSize;
PLINE_DEV_CAPS ldc;
PPX_ADAPTER ClAdapter;
ULONG SizeToMove;
LONG SizeLeft;
PUCHAR dst;
ULONG TotalSize;
//
// Synchronously get dev caps for this device
//
ClAdapter = TapiLine->TapiProvider->Adapter;
ldc = TapiLine->DevCaps;
SizeDevCaps = ldc->ulUsedSize;
//
// Add some space for our providerinfo if needed
//
if (ldc->ulProviderInfoSize == 0) {
NdisZeroMemory(ProviderInfo, sizeof(ProviderInfo));
ProviderInfoSize = wcslen(L"NDPROXY") * sizeof(WCHAR);
NdisMoveMemory((PUCHAR)ProviderInfo,
L"NDPROXY",
ProviderInfoSize);
//
// For NULL termination
//
ProviderInfoSize += sizeof(UNICODE_NULL);
SizeDevCaps += ProviderInfoSize;
}
//
// Add some space for our linename if needed
//
if ((ldc->ulLineNameSize == 0) &&
(ClAdapter != NULL) &&
(ClAdapter->MediaNameLength != 0)) {
PUCHAR dst;
NdisZeroMemory(LineName, sizeof(LineName));
dst = (PUCHAR)LineName;
NdisMoveMemory(dst,
(PUCHAR)(ClAdapter->MediaName),
ClAdapter->MediaNameLength);
(ULONG_PTR)dst += ClAdapter->MediaNameLength;
//
// ToDo! Shoud get the name of the adapter
// and insert here!
//
NdisMoveMemory(dst,
L" - Line",
wcslen(L" - Line") * sizeof(WCHAR));
(ULONG_PTR)dst +=
wcslen(L" - Line") * sizeof(WCHAR);
(VOID)
IntegerToWChar(TapiLine->CmLineID,
-4,
(WCHAR *)dst);
(ULONG_PTR)dst += 4 * sizeof(WCHAR);
LineNameSize = (ULONG)((ULONG_PTR)dst - (ULONG_PTR)LineName);
//
// For NULL termination
//
LineNameSize += sizeof(UNICODE_NULL);
SizeDevCaps += LineNameSize;
}
//
// Add some space for our device classes
//
DevClassesSize = sizeof(DevClassesList);
NdisZeroMemory((PUCHAR)DevClassesList,
sizeof(DevClassesList));
if (ClAdapter != NULL) {
GetAllDevClasses(ClAdapter,
DevClassesList,
&DevClassesSize);
}
SizeDevCaps += DevClassesSize;
ldc = &pNdisTapiGetDevCaps->LineDevCaps;
SizeToMove = (TapiLine->DevCaps->ulUsedSize > ldc->ulTotalSize) ?
ldc->ulTotalSize : TapiLine->DevCaps->ulUsedSize;
SizeLeft = ldc->ulTotalSize - SizeToMove;
//
// Save the total size
//
TotalSize = ldc->ulTotalSize;
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("PxTapiGetDevCaps: got device %x from ID %d: moving %d bytes\n",
TapiLine,
pNdisTapiGetDevCaps->ulDeviceID,
SizeToMove));
NdisMoveMemory((PUCHAR)ldc,
(PUCHAR)TapiLine->DevCaps,
SizeToMove);
ldc->ulNeededSize = SizeDevCaps;
ldc->ulTotalSize = TotalSize;
ldc->ulUsedSize = SizeToMove;
if (SizeLeft > 0) {
//
// If there is no provider info fill our proxy info
//
if (ldc->ulProviderInfoSize == 0) {
dst = (PUCHAR)ldc + ldc->ulUsedSize;
SizeToMove = (SizeLeft > (LONG)ProviderInfoSize) ?
ProviderInfoSize : SizeLeft;
NdisMoveMemory(dst,
(PUCHAR)ProviderInfo,
SizeToMove);
ldc->ulProviderInfoSize = SizeToMove;
ldc->ulProviderInfoOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
ldc->ulUsedSize += SizeToMove;
SizeLeft -= SizeToMove;
}
}
if (SizeLeft > 0) {
//
// If these is no line name fill in our line name
//
if (ldc->ulLineNameSize == 0 &&
ClAdapter != NULL &&
ClAdapter->MediaNameLength != 0) {
dst = (PUCHAR)ldc + ldc->ulUsedSize;
SizeToMove = (SizeLeft > (LONG)LineNameSize) ?
LineNameSize : SizeLeft;
NdisMoveMemory(dst,
(PUCHAR)LineName,
SizeToMove);
ldc->ulLineNameSize = SizeToMove;
ldc->ulLineNameOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
ldc->ulUsedSize += SizeToMove;
SizeLeft -= SizeToMove;
}
}
if (SizeLeft > 0) {
//
// Add the devclasses to the end
//
if (DevClassesSize > 0) {
dst = (PUCHAR)ldc + ldc->ulUsedSize;
SizeToMove = (SizeLeft > (LONG)DevClassesSize) ?
DevClassesSize : SizeLeft;
NdisMoveMemory(dst,
DevClassesList,
SizeToMove);
ldc->ulDeviceClassesSize = SizeToMove;
ldc->ulDeviceClassesOffset = (ULONG)((ULONG_PTR)dst-(ULONG_PTR)ldc);
ldc->ulUsedSize += SizeToMove;
SizeLeft -= SizeToMove;
}
}
} while (FALSE);
DEREF_TAPILINE_LOCKED(TapiLine);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevCaps: exit: used=%d, needed=%d, total=%d\n",
pNdisTapiGetDevCaps->LineDevCaps.ulUsedSize,
pNdisTapiGetDevCaps->LineDevCaps.ulNeededSize,
pNdisTapiGetDevCaps->LineDevCaps.ulTotalSize));
return (Status);
}
NDIS_STATUS
PxTapiAccept(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAccept: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAccept: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiAnswer(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_ANSWER pNdisTapiAnswer;
PPX_VC pVc = NULL;
NDIS_STATUS Status;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiAnswer: enter\n"));
pNdisTapiAnswer =
(PNDIS_TAPI_ANSWER)pNdisTapiRequest->Data;
if (!IsVcValid(pNdisTapiAnswer->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiAnswer: pVc invalid call handle %d\n",
pNdisTapiAnswer->hdCall));
return(NDIS_STATUS_TAPI_INVALCALLHANDLE);
}
NdisAcquireSpinLock(&pVc->Lock);
do {
if (pVc->State != PX_VC_OFFERING) {
//
// call in wrong state
//
PXDEBUGP(PXD_FATAL, PXM_TAPI, ("PxTapiAnswer: pVc VC %x/%x invalid state %x\n",
pVc, pVc->Flags,
pVc->ulCallState));
NdisReleaseSpinLock(&pVc->Lock);
Status = NDIS_STATUS_TAPI_INVALCALLSTATE;
break;
}
if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
PxStopIncomingCallTimeout(pVc);
}
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiAnswer: calling NdisClIncomingCallComplete\n"));
pVc->PrevState = pVc->State;
pVc->State = PX_VC_CONNECTED;
NdisReleaseSpinLock(&pVc->Lock);
NdisClIncomingCallComplete (NDIS_STATUS_SUCCESS,
pVc->ClVcHandle,
pVc->pCallParameters);
} while (FALSE);
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC(pVc);
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiAnswer: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiLineGetID(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Returns a handle to the client wich is returned to the tapi application.
This handle is only meaning full to the client and will vary depending
on the deviceclass.
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_ID pNdisTapiGetId =
(PNDIS_TAPI_GET_ID)pNdisTapiRequest->Data;
PVAR_STRING DeviceID = &pNdisTapiGetId->DeviceID;
PPX_VC pVc = NULL;
NDIS_HANDLE VcHandle = NULL;
PPX_CM_AF pCmAf;
PPX_CM_SAP pCmSap;
NDIS_STATUS Status;
LPCWSTR DevClass;
ULONG DevClassSize;
PPX_ADAPTER pAdapter;
DevClass =
(LPCWSTR)(((CHAR *)pNdisTapiGetId) + pNdisTapiGetId->ulDeviceClassOffset);
DevClassSize = pNdisTapiGetId->ulDeviceClassSize;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiLineGetID: enter. CallId %x, DevClass = %ls\n", pNdisTapiGetId->hdCall, DevClass));
if (pNdisTapiGetId->ulSelect != LINECALLSELECT_CALL) {
return (NDIS_STATUS_FAILURE);
}
//
// validate call handle and get call pointer
//
if (!IsVcValid(pNdisTapiGetId->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxNdisTapiGetId: pVc invalid call handle %d\n",
pNdisTapiGetId->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
NdisAcquireSpinLock(&pVc->Lock);
do {
//
// ToDo!
//
// If we already are working with a client
// we need to see if this is a mapping to the same
// client or to a different one. If it is to the
// same one just return the current handle. If it
// is to a different one we should either fail or
// tear the vc hand-off down from the current client
// and then hand-off to the new client.
//
if (pVc->CmVcHandle != NULL) {
Status = NDIS_STATUS_SUCCESS;
break;
}
if (pVc->State != PX_VC_CONNECTED) {
Status = NDIS_STATUS_TAPI_INVALCALLSTATE;
break;
}
pAdapter = pVc->Adapter;
//
// Find the sap/af of the client that we need to indicate this on
//
if (!PxAfAndSapFromDevClass(pAdapter,
DevClass,
&pCmAf,
&pCmSap)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiLineGetID: SAP not found!\n"));
Status = NDIS_STATUS_FAILURE;
break;
}
pVc->HandoffState = PX_VC_HANDOFF_OFFERING;
pVc->CmAf = pCmAf;
pVc->CmSap = pCmSap;
VcHandle = pVc->ClVcHandle;
NdisReleaseSpinLock(&pVc->Lock);
//
// Create the Vc
//
Status = NdisCoCreateVc(pAdapter->CmBindingHandle,
pCmAf->NdisAfHandle,
(NDIS_HANDLE)pVc->hdCall,
&VcHandle);
if (Status != NDIS_STATUS_SUCCESS) {
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiLineGetID: Client refused Vc CmAf %p DevClass %ls Status %x\n",
pCmAf, DevClass, Status));
Status = NDIS_STATUS_FAILURE;
//
// remove ref that was applied when we mapped the devclass
// to an af/sap.
//
DEREF_CM_AF(pCmAf);
NdisAcquireSpinLock(&pVc->Lock);
pVc->HandoffState = PX_VC_HANDOFF_IDLE;
break;
}
NdisAcquireSpinLock(&pVc->Lock);
pVc->CmVcHandle = VcHandle;
//
// Apply a reference on the vc for
// activating this call with the client.
// This ref is removed in PxCmCloseCall.
//
REF_VC(pVc);
NdisReleaseSpinLock(&pVc->Lock);
//
// Dispatch the incoming call to the client
//
Status =
NdisCmDispatchIncomingCall(pCmSap->NdisSapHandle,
pVc->CmVcHandle,
pVc->pCallParameters);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&pVc->Block);
}
if (Status != NDIS_STATUS_SUCCESS) {
//
// The client did not except the call
// delete the vc and go away.
//
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiLineGetID: Client rejected call VC %p, Status %x\n",
pVc, Status));
#ifdef CODELETEVC_FIXED
//
// Evidently the CoCreateVc is unbalanced
// when creating a proxy vc. The call to
// NdisCoDeleteVc will fail because the
// Vc is still active.
// ToDo! Investigate this with ndis
//
Status =
NdisCoDeleteVc(pVc->CmVcHandle);
#endif
//
// remove ref that was applied when we mapped the devclass
// to an af/sap.
//
DEREF_CM_AF(pCmAf);
NdisAcquireSpinLock(&pVc->Lock);
#ifdef CODELETEVC_FIXED
if (Status == NDIS_STATUS_SUCCESS) {
pVc->CmVcHandle = NULL;
}
#endif
pVc->HandoffState = PX_VC_HANDOFF_IDLE;
//
// Remove the reference we applied before
// dispatching incoming call to client.
// We do not need to do all of the deref code
// because of the ref applied at entry to
// this function
//
pVc->RefCount--;
break;
}
NdisCmDispatchCallConnected(pVc->CmVcHandle);
NdisAcquireSpinLock(&pVc->Lock);
//
// If we are still in the offering state
// we can safely move to connected at this
// point. We might not be in offering if
// right after we connected the client
// did an NdisClCloseCall before we could
// reacquire the spinlock.
//
if (pVc->HandoffState == PX_VC_HANDOFF_OFFERING) {
pVc->HandoffState = PX_VC_HANDOFF_CONNECTED;
}
} while (FALSE);
//
// If we get here and we are not in the connected
// state something happened to tear our call
// down with the client. This could have been
// an error attempting to create the call with the
// client or we received either a
// tapidrop from tapi
// incomingclosecall from cm
//
if (pVc->State != PX_VC_CONNECTED) {
Status =
PxCloseCallWithCl(pVc);
if ((Status != NDIS_STATUS_PENDING) &&
(pVc->Flags & PX_VC_CLEANUP_CM)) {
PxCloseCallWithCm(pVc);
}
Status = NDIS_STATUS_FAILURE;
} else if (Status == NDIS_STATUS_SUCCESS) {
Status = NdisCoGetTapiCallId(pVc->CmVcHandle,
DeviceID);
//
// ToDo?: If status is failure here, do we need to do anything? In our
// case this should be OK, because the TSP ensures the size of
// the VAR_STRING is right, and that's the only thing that can
// cause a failure.
//
}
PXDEBUGP(PXD_LOUD, PXM_TAPI,
("PxTapiLineGetID: Vc %p, Status %x\n", pVc, Status));
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
return Status;
}
NDIS_STATUS
PxTapiClose (
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI is closing it's handle to our device. We shouldn't see any further requests or
send any TAPI events after completing this function.
In the current design, we are the sole owner of all VCs (i.e. there are no 'pass-through' or monitor-only
functions in the Proxy). TAPI should not call this func before all calls have been closed and all apps
have disconnected.
NOTE: this function is also called by TAPI after we send it a LINE_REMOVE message, indicating that
the adapter has been unbound. In this case, too, we should already have closed all calls/freed VCs and
associated structures.
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_CLOSE pTapiClose =
(PNDIS_TAPI_CLOSE)pNdisTapiRequest->Data;
PPX_TAPI_LINE TapiLine;
PPX_VC pVc;
PPX_TAPI_PROVIDER TapiProvider;
PPX_CL_SAP pClSap;
PPX_CL_AF pClAf;
NDIS_STATUS Status;
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("PxTapiClose: ID: %d\n", pTapiClose->hdLine));
//
// validate line handle and get line pointer
//
if (!IsTapiLineValid((ULONG)pTapiClose->hdLine, &TapiLine)) {
PXDEBUGP (PXD_WARNING, PXM_TAPI, ("PxTapiClose: NDISTAPIERR_BADDEVICEID: line = %x\n", pTapiClose->hdLine));
return (NDISTAPIERR_BADDEVICEID);
}
NdisAcquireSpinLock(&TapiLine->Lock);
TapiLine->DevStatus->ulNumOpens--;
if (TapiLine->DevStatus->ulNumOpens != 0) {
NdisReleaseSpinLock(&TapiLine->Lock);
return (NDIS_STATUS_SUCCESS);
}
pClAf = TapiLine->ClAf;
pClSap = TapiLine->ClSap;
TapiLine->ClSap = NULL;
TapiLine->DevStatus->ulOpenMediaModes = 0;
NdisReleaseSpinLock(&TapiLine->Lock);
//
// If we have any active Vc's on this line we need
// tear them down.
//
if (pClAf != NULL) {
NdisAcquireSpinLock(&pClAf->Lock);
REF_CL_AF(pClAf);
#if 0
while (!IsListEmpty(&pClAf->VcList)) {
PLIST_ENTRY Entry;
PPX_VC pActiveVc;
Entry = RemoveHeadList(&pClAf->VcList);
InsertHeadList(&pClAf->VcClosingList, Entry);
pActiveVc =
CONTAINING_RECORD(Entry, PX_VC, ClAfLinkage);
NdisReleaseSpinLock(&pClAf->Lock);
NdisAcquireSpinLock(&pActiveVc->Lock);
if (!(pActiveVc->CloseFlags & PX_VC_TAPI_CLOSE)) {
REF_VC(pActiveVc);
pActiveVc->CloseFlags |= PX_VC_TAPI_CLOSE;
PxVcCleanup(pActiveVc, 0);
PxTapiCompleteAllIrps(pActiveVc, NDIS_STATUS_SUCCESS);
//
// Remove the ref applied in the make call or call offering
// indication. We do not need the full deref code because
// of the ref applied at entry.
//
pActiveVc->RefCount--;
DEREF_VC_LOCKED(pActiveVc);
}
NdisAcquireSpinLock(&pClAf->Lock);
}
#endif
//
// If we have a sap registered on this line we need
// to close it.
//
if (pClSap != NULL) {
// If the SAP is opened then we need to close it
if (pClSap->State == PX_SAP_OPENED) {
RemoveEntryList(&pClSap->Linkage);
InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
NdisReleaseSpinLock(&pClAf->Lock);
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
if (Status != NDIS_STATUS_PENDING) {
PxClDeregisterSapComplete(Status, pClSap);
}
NdisAcquireSpinLock(&pClAf->Lock);
}
}
DEREF_CL_AF_LOCKED(pClAf);
}
DEREF_TAPILINE(TapiLine);
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiCloseCall(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
NDIS_STATUS Status;
PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall =
(PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequest->Data;
PPX_VC pVc;
PPX_TAPI_LINE TapiLine;
if (!IsVcValid(pNdisTapiCloseCall->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiCloseCall: invalid call handle %d\n",
pNdisTapiCloseCall->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
PXDEBUGP (PXD_TAPI, PXM_TAPI,
("PxTapiCloseCall: enter. VC = %x, State = %x\n",
pVc, pVc->State));
NdisAcquireSpinLock(&pVc->Lock);
pVc->CloseFlags |= PX_VC_TAPI_CLOSECALL;
//
// Check the Vc state and act accordingly
//
PxVcCleanup(pVc, 0);
PxTapiCompleteAllIrps(pVc, NDIS_STATUS_SUCCESS);
//
// Remove the ref applied in the make call or call offering
// indication. We do not need the full deref code because
// of the ref applied at entry.
//
pVc->RefCount--;
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiCloseCall: exit.\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiConditionalMediaDetection(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConditionalMediaDetection: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConditionalMediaDetection: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiConfigDialog (
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConfigDialog: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiConfigDialog: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiDevSpecific(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
D for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDevSpecific: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDevSpecific: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiDial(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDial: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiDial: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiDrop(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Drop the call without deallocating the VC.
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PPX_VC pVc;
PIRP Irp;
PNDIS_TAPI_DROP pNdisTapiDrop =
(PNDIS_TAPI_DROP)pNdisTapiRequest->Data;
if (!IsVcValid(pNdisTapiDrop->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiDrop: invalid call handle %d\n",
pNdisTapiDrop->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("PxTapiDrop enter: Vc: %p VcState: %x CallState: %x\n", pVc, pVc->State, pVc->ulCallState ));
NdisAcquireSpinLock(&pVc->Lock);
Irp = pNdisTapiRequest->Irp;
IoSetCancelRoutine(Irp, PxCancelSetQuery);
//
// Insert the request in the Vc's pending list
//
InsertTailList(&pVc->PendingDropReqs,
&pNdisTapiRequest->Linkage);
pVc->CloseFlags |= PX_VC_TAPI_DROP;
//
// Check the Vc state and act accordingly
//
Status =
PxVcCleanup(pVc, PX_VC_DROP_PENDING);
if (Status != NDIS_STATUS_PENDING) {
RemoveEntryList(&pNdisTapiRequest->Linkage);
IoSetCancelRoutine(Irp, NULL);
}
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
return (Status);
}
NDIS_STATUS
PxTapiGetAddressCaps(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps =
(PNDIS_TAPI_GET_ADDRESS_CAPS) pNdisTapiRequest->Data;
PPX_TAPI_LINE TapiLine;
PPX_TAPI_ADDR TapiAddr;
PPX_ADAPTER ClAdapter;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
if (!IsTapiDeviceValid(pNdisTapiRequest->ulDeviceID, &TapiLine)) {
PXDEBUGP (PXD_WARNING, PXM_TAPI, ( "PxTapiGetAddressCaps: NDISTAPIERR_BADDEVICEID: line = %x\n", pNdisTapiRequest->ulDeviceID));
return (NDISTAPIERR_BADDEVICEID);
}
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("PxTapiGetAddressCaps: got device %p from ID %d\n",
TapiLine, pNdisTapiRequest->ulDeviceID));
NdisAcquireSpinLock(&TapiLine->Lock);
do {
ULONG DevClassesSize = 0;
USHORT DevClassesList[512];
ULONG SizeToMove;
ULONG TotalSize;
ULONG SizeLeft;
PLINE_ADDRESS_CAPS In, Out;
//
// Get the tapi address that we are interested in
//
if (!IsAddressValid(TapiLine,
pNdisTapiGetAddressCaps->ulAddressID,
&TapiAddr)) {
Status = NDIS_STATUS_TAPI_INVALADDRESSID;
break;
}
In = TapiAddr->Caps;
Out = &pNdisTapiGetAddressCaps->LineAddressCaps;
//
// Add some space for our device classes
//
DevClassesSize = sizeof(DevClassesList);
NdisZeroMemory((PUCHAR)DevClassesList,
sizeof(DevClassesList));
if (TapiLine->TapiProvider->Adapter != NULL) {
GetAllDevClasses(TapiLine->TapiProvider->Adapter,
DevClassesList,
&DevClassesSize);
}
//
// Synchronously get Address caps for this device
//
SizeToMove = (In->ulUsedSize > Out->ulTotalSize) ?
Out->ulTotalSize : In->ulUsedSize;
TotalSize = Out->ulTotalSize;
NdisMoveMemory((PUCHAR)Out, (PUCHAR)In, SizeToMove);
SizeLeft =
TotalSize - SizeToMove;
Out->ulTotalSize = TotalSize;
Out->ulUsedSize = SizeToMove;
Out->ulNeededSize =
In->ulUsedSize + DevClassesSize;
if (SizeLeft > 0) {
//
// If these is room fill in our devclasses
//
if (DevClassesSize > 0) {
PUCHAR dst;
dst = (PUCHAR)Out + Out->ulUsedSize;
SizeToMove = (SizeLeft > DevClassesSize) ?
DevClassesSize : SizeLeft;
NdisMoveMemory(dst, DevClassesList, SizeToMove);
Out->ulDeviceClassesSize = SizeToMove;
Out->ulDeviceClassesOffset =
(ULONG)((ULONG_PTR)dst - (ULONG_PTR)Out);
Out->ulUsedSize += SizeToMove;
SizeLeft -= SizeToMove;
}
}
} while (FALSE);
DEREF_TAPILINE_LOCKED(TapiLine);
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetAddressCaps: exit. \n"));
return (Status);
}
NDIS_STATUS
PxTapiGetAddressID(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_ADDRESS_ID TapiBuffer =
(PNDIS_TAPI_GET_ADDRESS_ID) pNdisTapiRequest->Data;
PPX_TAPI_LINE TapiLine;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: enter\n"));
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetAddressID: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
return(NDISTAPIERR_BADDEVICEID);
}
NdisAcquireSpinLock(&TapiLine->Lock);
//
// ToDo!
//
TapiBuffer->ulAddressID = 0;
DEREF_TAPILINE_LOCKED(TapiLine);
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressID: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiGetAddressStatus(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
Placeholder for TAPI OID action routines
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: enter\n"));
//
// ToDo!
//
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetAddressStatus: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiGetCallAddressID(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_CALL_ADDRESS_ID TapiBuffer =
(PNDIS_TAPI_GET_CALL_ADDRESS_ID)pNdisTapiRequest->Data;
PPX_VC pVc;
if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallAddressID: invalid call handle %d\n",
TapiBuffer->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: Vc: %p\n", pVc));
NdisAcquireSpinLock(&pVc->Lock);
TapiBuffer->ulAddressID = pVc->TapiAddr->AddrId;
DEREF_VC_LOCKED(pVc);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallAddressID: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiGetCallInfo(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_CALL_INFO TapiBuffer =
(PNDIS_TAPI_GET_CALL_INFO)pNdisTapiRequest->Data;
PPX_VC pVc;
PPX_TAPI_LINE TapiLine;
LINE_CALL_INFO* CallInfo;
LINE_CALL_INFO* OutCallInfo = &TapiBuffer->LineCallInfo;
ULONG VarDataSize = 0; // Total available
ULONG VarDataUsed = 0;
if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallInfo: invalid call handle %d\n",
TapiBuffer->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
NdisAcquireSpinLock(&pVc->Lock);
//
// Make sure we have enough space to copy everything over
//
CallInfo = pVc->CallInfo;
TapiLine = pVc->TapiLine;
VarDataSize =
pNdisTapiRequest->ulDataSize - sizeof(NDIS_TAPI_GET_CALL_INFO);
PXDEBUGP (PXD_TAPI, PXM_TAPI,
("PxTapiGetCallInfo: enter. pVc = %p, AvailSize = %x, needed = %x\n",
pVc, OutCallInfo->ulTotalSize, CallInfo->ulUsedSize));
OutCallInfo->ulNeededSize = CallInfo->ulUsedSize;
//
// Patch up the Id here. We store it in our callinfo
// block in terms of the call managers 0 based Id. We
// need to give tapi the Id it is looking for which is
// stored in the tapiline.
//
OutCallInfo->ulLineDeviceID = TapiLine->ulDeviceID;
OutCallInfo->ulAddressID = CallInfo->ulAddressID;
OutCallInfo->ulBearerMode = CallInfo->ulBearerMode;
OutCallInfo->ulRate = CallInfo->ulRate;
OutCallInfo->ulMediaMode = CallInfo->ulMediaMode;
OutCallInfo->ulAppSpecific = CallInfo->ulAppSpecific;
OutCallInfo->ulCallID = 0;
OutCallInfo->ulRelatedCallID = 0;
OutCallInfo->ulCallParamFlags = 0;
OutCallInfo->DialParams.ulDialPause = 0;
OutCallInfo->DialParams.ulDialSpeed = 0;
OutCallInfo->DialParams.ulDigitDuration = 0;
OutCallInfo->DialParams.ulWaitForDialtone = 0;
OutCallInfo->ulReason = CallInfo->ulReason;
OutCallInfo->ulCompletionID = 0;
OutCallInfo->ulCountryCode = 0;
OutCallInfo->ulTrunk = (ULONG)-1;
//
// Do the CallerID
//
if (CallInfo->ulCallerIDSize) {
if (((VarDataUsed + CallInfo->ulCallerIDSize) <= VarDataSize) &&
((CallInfo->ulCallerIDOffset + CallInfo->ulCallerIDSize) <= CallInfo->ulUsedSize)) {
OutCallInfo->ulCallerIDSize = CallInfo->ulCallerIDSize;
OutCallInfo->ulCallerIDFlags = CallInfo->ulCallerIDFlags;
OutCallInfo->ulCallerIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCallerIDOffset,
(PUCHAR)(CallInfo)+CallInfo->ulCallerIDOffset,
CallInfo->ulCallerIDSize);
VarDataUsed += CallInfo->ulCallerIDSize;
pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLERID;
}
} else {
OutCallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL;
OutCallInfo->ulCallerIDSize = 0;
OutCallInfo->ulCallerIDOffset = 0;
}
OutCallInfo->ulCallerIDNameSize = 0;
OutCallInfo->ulCallerIDNameOffset = 0;
//
// Do the CalledID
//
if (CallInfo->ulCalledIDSize) {
if (((VarDataUsed + CallInfo->ulCalledIDSize) <= VarDataSize) &&
((CallInfo->ulCalledIDOffset + CallInfo->ulCalledIDSize) <= CallInfo->ulUsedSize)) {
OutCallInfo->ulCalledIDFlags = CallInfo->ulCalledIDFlags;
OutCallInfo->ulCalledIDSize = CallInfo->ulCalledIDSize;
OutCallInfo->ulCalledIDOffset = sizeof (LINE_CALL_INFO) + VarDataUsed;
NdisMoveMemory ( (PUCHAR)(OutCallInfo)+OutCallInfo->ulCalledIDOffset,
(PUCHAR)(CallInfo)+CallInfo->ulCalledIDOffset,
CallInfo->ulCalledIDSize);
VarDataUsed += CallInfo->ulCalledIDSize;
pVc->ulCallInfoFieldsChanged |= LINECALLINFOSTATE_CALLEDID;
}
} else {
OutCallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL;
OutCallInfo->ulCalledIDSize = 0;
OutCallInfo->ulCalledIDOffset = 0;
}
OutCallInfo->ulCalledIDNameSize = 0;
OutCallInfo->ulCalledIDNameOffset = 0;
OutCallInfo->ulCallStates = LINECALLSTATE_IDLE |
LINECALLSTATE_OFFERING |
LINECALLSTATE_CONNECTED |
LINECALLSTATE_PROCEEDING |
LINECALLSTATE_DISCONNECTED |
LINECALLSTATE_SPECIALINFO |
LINECALLSTATE_UNKNOWN;
OutCallInfo->ulOrigin = (pVc->Flags & PX_VC_OWNER) ? LINECALLORIGIN_EXTERNAL : LINECALLORIGIN_OUTBOUND;
OutCallInfo->ulReason = LINECALLREASON_UNAVAIL;
OutCallInfo->ulCompletionID = 0;
OutCallInfo->ulConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
OutCallInfo->ulConnectedIDSize = 0;
OutCallInfo->ulConnectedIDOffset = 0;
OutCallInfo->ulConnectedIDNameSize = 0;
OutCallInfo->ulConnectedIDNameOffset = 0;
OutCallInfo->ulRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
OutCallInfo->ulRedirectionIDSize = 0;
OutCallInfo->ulRedirectionIDOffset = 0;
OutCallInfo->ulRedirectionIDNameSize = 0;
OutCallInfo->ulRedirectionIDNameOffset = 0;
OutCallInfo->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
OutCallInfo->ulRedirectingIDSize = 0;
OutCallInfo->ulRedirectingIDOffset = 0;
OutCallInfo->ulRedirectingIDNameSize = 0;
OutCallInfo->ulRedirectingIDNameOffset = 0;
OutCallInfo->ulDisplaySize = 0;
OutCallInfo->ulDisplayOffset = 0;
OutCallInfo->ulUserUserInfoSize = 0;
OutCallInfo->ulUserUserInfoOffset = 0;
OutCallInfo->ulHighLevelCompSize = 0;
OutCallInfo->ulHighLevelCompOffset = 0;
OutCallInfo->ulLowLevelCompSize = 0;
OutCallInfo->ulLowLevelCompOffset = 0;
OutCallInfo->ulChargingInfoSize = 0;
OutCallInfo->ulChargingInfoOffset = 0;
OutCallInfo->ulTerminalModesSize = 0;
OutCallInfo->ulTerminalModesOffset = 0;
OutCallInfo->ulDevSpecificSize = 0;
OutCallInfo->ulDevSpecificOffset = 0;
OutCallInfo->ulNeededSize =
OutCallInfo->ulUsedSize = sizeof(LINE_CALL_INFO) + VarDataUsed;
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiGetCallStatus (
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_CALL_STATUS TapiBuffer =
(PNDIS_TAPI_GET_CALL_STATUS)pNdisTapiRequest->Data;
PPX_VC pVc;
LINE_CALL_INFO* CallInfo;
LINE_CALL_STATUS* CallStatus = &TapiBuffer->LineCallStatus;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetCallStatus: enter\n"));\
if (!IsVcValid(TapiBuffer->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiGetCallStatus: invalid call handle %d\n",
TapiBuffer->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
NdisAcquireSpinLock(&pVc->Lock);
CallInfo = pVc->CallInfo;
CallStatus->ulUsedSize = sizeof(LINE_CALL_STATUS);
CallStatus->ulCallState = pVc->ulCallState;
//
// fill the mode depending on the call state
//
switch (pVc->ulCallState) {
case LINECALLSTATE_IDLE:
default:
CallStatus->ulCallStateMode = 0;
CallStatus->ulCallFeatures = 0;
break;
case LINECALLSTATE_CONNECTED:
CallStatus->ulCallStateMode = 0;
CallStatus->ulCallFeatures = LINECALLFEATURE_DROP;
break;
case LINECALLSTATE_OFFERING:
CallStatus->ulCallStateMode = 0;
CallStatus->ulCallFeatures = LINECALLFEATURE_ANSWER;
break;
case LINECALLSTATE_DISCONNECTED:
if (pVc->ulCallStateMode == 0x11 )
CallStatus->ulCallStateMode = LINEDISCONNECTMODE_BUSY;
else
CallStatus->ulCallStateMode = LINEDISCONNECTMODE_NOANSWER;
break;
case LINECALLSTATE_BUSY:
CallStatus->ulCallStateMode = LINEBUSYMODE_UNAVAIL;
break;
case LINECALLSTATE_SPECIALINFO:
// if(cm->NoActiveLine)
// CallStatus->ulCallStateMode = LINESPECIALINFO_NOCIRCUIT;
CallStatus->ulCallStateMode = 0;
break;
}
CallStatus->ulDevSpecificSize = 0;
CallStatus->ulDevSpecificOffset = 0;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("GetCallStatus: VC %x/%x, CallSt %x, Mode %x, Features %x\n",
pVc, pVc->Flags,
CallStatus->ulCallState,
CallStatus->ulCallStateMode,
CallStatus->ulCallFeatures));
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiGetDevConfig(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetDevConfig: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiGetExtensionID(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_EXTENSION_ID TapiBuffer = (PNDIS_TAPI_GET_EXTENSION_ID)pNdisTapiRequest->Data;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: enter\n"));
// TapiBuffer->LineExtensionID.ulExtensionID0 = 0;
// TapiBuffer->LineExtensionID.ulExtensionID1 = 0;
// TapiBuffer->LineExtensionID.ulExtensionID2 = 0;
// TapiBuffer->LineExtensionID.ulExtensionID3 = 0;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetExtensionID: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiGetLineDevStatus(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_GET_LINE_DEV_STATUS TapiBuffer =
(PNDIS_TAPI_GET_LINE_DEV_STATUS)pNdisTapiRequest->Data;
PPX_TAPI_LINE TapiLine;
PX_ADAPTER *pAdapter;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: enter\n"));
//
// validate line handle and get line pointer
//
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->hdLine));
return (NDISTAPIERR_BADDEVICEID);
}
NdisAcquireSpinLock(&TapiLine->Lock);
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiGetLineDevStatus: got device %p from ID %d\n", TapiLine, TapiBuffer->hdLine));
//
// Get MediaModes and Current Calls
//
TapiBuffer->LineDevStatus.ulOpenMediaModes =
TapiLine->DevStatus->ulOpenMediaModes;
TapiBuffer->LineDevStatus.ulNumActiveCalls =
TapiLine->DevStatus->ulNumActiveCalls;
TapiBuffer->LineDevStatus.ulDevStatusFlags =
TapiLine->DevStatus->ulDevStatusFlags;
DEREF_TAPILINE_LOCKED(TapiLine);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiGetLineDevStatus: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiNegotiateExtVersion(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion =
(PNDIS_TAPI_NEGOTIATE_EXT_VERSION) pNdisTapiRequest->Data;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: enter\n"));
pNdisTapiNegotiateExtVersion->ulExtVersion = 0;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiNegotiateExtVersion: exit NDIS_STATUS_TAPI_OPERATIONUNAVAIL\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiSendUserUserInfo(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: enter\n"));
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSendUserUserInfo: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiSetAppSpecific(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific =
(PNDIS_TAPI_SET_APP_SPECIFIC)(pNdisTapiRequest->Data);
PPX_VC pVc;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: enter\n"));
if (!IsVcValid(pNdisTapiSetAppSpecific->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetAppSpecific: pVc invalid call handle %d\n",
pNdisTapiSetAppSpecific->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
NdisAcquireSpinLock(&pVc->Lock);
//
// Get the VC, and re-set the app specific longword.
//
pVc->CallInfo->ulAppSpecific =
pNdisTapiSetAppSpecific->ulAppSpecific;
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetAppSpecific: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiSetCallParams(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetCallParams: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiSetDefaultMediaDetection(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION TapiBuffer =
(PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)pNdisTapiRequest->Data;
PPX_CL_AF pClAf = NULL;
PPX_CL_SAP pClSap = NULL;
PCO_SAP pCoSap;
PPX_TAPI_LINE TapiLine = NULL;
NDIS_STATUS Status;
BOOLEAN Found = FALSE;
PPX_TAPI_PROVIDER TapiProvider;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: enter\n"));
//
// validate line handle and get line pointer
//
if (!IsTapiLineValid((ULONG)TapiBuffer->hdLine, &TapiLine)) {
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiSetDefaultMediaDetection: NDISTAPIERR_BADDEVICEID: line = %x\n",
TapiBuffer->hdLine));
return (NDISTAPIERR_BADDEVICEID);
}
PXDEBUGP(PXD_LOUD, PXM_TAPI,
("PxTapiSetDefaultMediaDetection: got TapiLine %p from ID %d\n",
TapiLine, TapiBuffer->hdLine));
NdisAcquireSpinLock(&TapiLine->Lock);
do {
//
// Is this line in service? (does it have an valid af?)
//
if (!(TapiLine->DevStatus->ulDevStatusFlags &
LINEDEVSTATUSFLAGS_INSERVICE)) {
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiSetDefaultMediaDetection: Line not in service!\n"));
NdisReleaseSpinLock(&TapiLine->Lock);
Status = NDIS_STATUS_TAPI_INVALLINESTATE;
break;
}
//
// Make sure this line supports these media modes
//
if ((TapiBuffer->ulMediaModes & TapiLine->DevCaps->ulMediaModes) !=
TapiBuffer->ulMediaModes) {
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiSetDefaultMediaDetection: invalid media mode\n"));
NdisReleaseSpinLock(&TapiLine->Lock);
Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
break;
}
//
// See if we already have these media modes open
//
if ((TapiBuffer->ulMediaModes &
~TapiLine->DevStatus->ulOpenMediaModes) == 0) {
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiSetDefaultMediaDetection: Already have a sap!\n"));
NdisReleaseSpinLock(&TapiLine->Lock);
Status = NDIS_STATUS_SUCCESS;
break;
}
TapiLine->DevStatus->ulOpenMediaModes |=
TapiBuffer->ulMediaModes;
pClAf = TapiLine->ClAf;
pClSap = TapiLine->ClSap;
TapiLine->ClSap = NULL;
NdisReleaseSpinLock(&TapiLine->Lock);
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiSetDefaultMediaDetection: TapiLine: %p, pClAf: %p, MediaModes: %x\n",
TapiLine, pClAf, TapiLine->DevStatus->ulOpenMediaModes));
NdisAcquireSpinLock(&pClAf->Lock);
REF_CL_AF(pClAf);
if (pClSap != NULL) {
//
// We already have a sap on this line. We only need one
// per line so let's deregister the old one before registering
// the new one.
//
RemoveEntryList(&pClSap->Linkage);
InsertTailList(&pClAf->ClSapClosingList, &pClSap->Linkage);
NdisReleaseSpinLock(&pClAf->Lock);
InterlockedExchange((PLONG)&pClSap->State, PX_SAP_CLOSING);
Status = NdisClDeregisterSap(pClSap->NdisSapHandle);
if (Status != NDIS_STATUS_PENDING) {
PxClDeregisterSapComplete(Status, pClSap);
}
} else {
NdisReleaseSpinLock(&pClAf->Lock);
}
//
// Get a SAP translation for this Media Mode setting.
// The function is called with the Af lock held and
// returns with the Af lock released!
//
pClSap = (*pClAf->AfGetNdisSap)(pClAf, TapiLine);
if (pClSap == NULL) {
Status = NDIS_STATUS_RESOURCES;
break;
}
NdisAcquireSpinLock(&pClAf->Lock);
InsertTailList(&pClAf->ClSapList, &pClSap->Linkage);
REF_CL_AF(pClAf);
NdisReleaseSpinLock(&pClAf->Lock);
//
// Register the new sap
//
Status = NdisClRegisterSap(pClAf->NdisAfHandle,
pClSap,
pClSap->CoSap,
&pClSap->NdisSapHandle);
if (Status != NDIS_STATUS_PENDING) {
PxClRegisterSapComplete(Status,
pClSap,
pClSap->CoSap,
pClSap->NdisSapHandle);
}
} while (FALSE);
DEREF_CL_AF(pClAf);
DEREF_TAPILINE(TapiLine);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDefaultMediaDetection: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiSetDevConfig(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetDevConfig: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiSetMediaMode(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode =
(PNDIS_TAPI_SET_MEDIA_MODE)(pNdisTapiRequest->Data);
PPX_VC pVc;
PPX_TAPI_LINE TapiLine;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: enter\n"));
if (!IsVcValid(pNdisTapiSetMediaMode->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI, ("PxTapiSetMediaMode: pVc invalid call handle %d\n",
pNdisTapiSetMediaMode->hdCall));
return NDIS_STATUS_TAPI_INVALCALLHANDLE;
}
NdisAcquireSpinLock(&pVc->Lock);
TapiLine = pVc->TapiAddr->TapiLine;
if ((TapiLine->DevCaps->ulMediaModes & pNdisTapiSetMediaMode->ulMediaMode)) {
pVc->CallInfo->ulMediaMode = pNdisTapiSetMediaMode->ulMediaMode;
} else {
Status = NDIS_STATUS_TAPI_INVALMEDIAMODE;
}
//
// Deref for ref applied at entry when
// validating the vc
//
DEREF_VC_LOCKED(pVc);
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSetMediaMode: exit\n"));
return (Status);
}
NDIS_STATUS
PxTapiSetStatusMessages(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSeStatusMessages: enter\n"));
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("PxTapiSetStatusMessages: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiOpen(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PNDIS_TAPI_OPEN TapiBuffer =
(PNDIS_TAPI_OPEN)pNdisTapiRequest->Data;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PPX_TAPI_LINE TapiLine;
PPX_TAPI_ADDR TapiAddr;
PNDISTAPI_OPENDATA OpenData;
PX_ADAPTER *Adapter;
ULONG n;
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: enter\nn"));
if (!IsTapiDeviceValid(TapiBuffer->ulDeviceID, &TapiLine)) {
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOPEN: NDISTAPIERR_BADDEVICEID: line = %x\n", TapiBuffer->ulDeviceID));
return(NDISTAPIERR_BADDEVICEID);
}
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiOpen: got device %p from ID %d\n", TapiLine, TapiBuffer->ulDeviceID));
NdisAcquireSpinLock(&TapiLine->Lock);
if (!(TapiLine->DevStatus->ulDevStatusFlags &
LINEDEVSTATUSFLAGS_INSERVICE)) {
NdisReleaseSpinLock(&TapiLine->Lock);
return(NDISTAPIERR_DEVICEOFFLINE);
}
//
// Stick TAPI's line handle into the device
//
TapiLine->htLine = (HTAPI_LINE)TapiBuffer->htLine;
TapiLine->DevStatus->ulNumOpens++;
//
// Stick our line handle into the out param. This is the context that will be
// passed to us in subsequent API calls on this open line device. Use the device ID.
//
TapiBuffer->hdLine = TapiLine->hdLine;
//
// Stick the miniport GUID and the mediatype into the variable data portion of the
// TAPI Open call (req'd for NDISWAN/Tonybe)
//
Adapter = TapiLine->TapiProvider->Adapter;
OpenData = (PNDISTAPI_OPENDATA)
((PUCHAR)pNdisTapiRequest->Data + sizeof(NDIS_TAPI_OPEN));
RtlMoveMemory(&OpenData->Guid,
&Adapter->Guid,
sizeof(OpenData->Guid));
OpenData->MediaType = Adapter->MediumSubType;
DEREF_TAPILINE_LOCKED(TapiLine);
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiOpen: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiProviderInit(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
fea142c4
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderInit: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiProviderShutdown(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
fea142c4
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiProviderShutdown: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiSecureCall(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSecureCall: exit\n"));
return (NDIS_STATUS_TAPI_OPERATIONUNAVAIL);
}
NDIS_STATUS
PxTapiSelectExtVersion(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
/*++
Routine Description:
TAPI OID action routine
Arguments:
pNdisTapiRequest -- the request that arrived in an IRP system buffer
Return Value:
--*/
{
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: enter\n"));
PXDEBUGP (PXD_TAPI, PXM_TAPI, ("PxTapiSelectExtVersion: exit\n"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
PxTapiGatherDigits(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
{
NDIS_STATUS Status = STATUS_SUCCESS;
PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits = NULL;
NDIS_HANDLE NdisBindingHandle, NdisAfHandle, NdisVcHandle;
PPX_VC pVc = NULL;
PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiGatherDigits: Enter\n"));
pNdisTapiGatherDigits =
(PNDIS_TAPI_GATHER_DIGITS)pNdisTapiRequest->Data;
do {
PX_REQUEST ProxyRequest;
PNDIS_REQUEST NdisRequest;
PIRP Irp;
if (!IsVcValid(pNdisTapiGatherDigits->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiGatherDigits: Invalid call - Setting "
"Status NDISTAPIERR_BADDEVICEID\n"));
Status = NDISTAPIERR_BADDEVICEID;
break;
}
NdisAcquireSpinLock(&pVc->Lock);
//
// If we're monitoring digits (ala lineMonitorDigits) then we can't gather digits.
//
if (pVc->ulMonitorDigitsModes != 0) {
NdisReleaseSpinLock(&pVc->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
if (pVc->PendingGatherDigits != NULL) {
//
// Check if the buffer passed to TSPI_lineGatherDigits was NULL. If so, then this
// is a request to cancel digit gathering that was previously initiated. If not, then
// the app is trying to do two lineGatherDigits() operations at once and we have to
// fail this.
//
if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
pVc->PendingGatherDigits = NULL;
PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
NdisReleaseSpinLock(&pVc->Lock);
Status = NDIS_STATUS_SUCCESS;
break;
} else {
NdisReleaseSpinLock(&pVc->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
} else if (pNdisTapiGatherDigits->lpsOrigDigitsBuffer == NULL) {
//
// Trying to cancel digit detection even though it wasn't started. Fail this.
//
NdisReleaseSpinLock(&pVc->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
Irp = pNdisTapiRequest->Irp;
IoSetCancelRoutine(Irp, PxCancelSetQuery);
//
// Store the unique request ID in the VC - this will be used later to retrieve the
// original IRP.
//
pVc->PendingGatherDigits = pNdisTapiRequest;
NdisReleaseSpinLock(&pVc->Lock);
//
// Initialize the timer that will be used to implement the digit timeouts.
//
NdisInitializeTimer(&pVc->DigitTimer,
PxDigitTimerRoutine,
(PVOID)pVc);
//
// Fill out our request structure.
//
NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
PxInitBlockStruc(&ProxyRequest.Block);
NdisRequest = &ProxyRequest.NdisRequest;
NdisRequest->RequestType =
NdisRequestSetInformation;
NdisRequest->DATA.SET_INFORMATION.Oid =
OID_CO_TAPI_REPORT_DIGITS;
NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
(PVOID)&pNdisTapiGatherDigits->ulDigitModes; // This is the NDIS_TAPI_GATHER_DIGITS structure
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
sizeof(pNdisTapiGatherDigits->ulDigitModes);
Status =
NdisCoRequest(pVc->Adapter->ClBindingHandle,
pVc->ClAf->NdisAfHandle,
pVc->ClVcHandle,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&ProxyRequest.Block);
}
if (Status != NDIS_STATUS_SUCCESS) {
NdisAcquireSpinLock(&pVc->Lock);
pVc->PendingGatherDigits = NULL;
IoSetCancelRoutine(Irp, NULL);
NdisReleaseSpinLock(&pVc->Lock);
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiGatherDigits: NdisCoRequest failed\n"));
break;
}
//
// Start the timer for the first digit timeout. Ref the VC here because otherwise it might
// go away before the timer fires.
//
if (pNdisTapiGatherDigits->ulFirstDigitTimeout) {
NdisAcquireSpinLock(&pVc->Lock);
REF_VC(pVc);
NdisReleaseSpinLock(&pVc->Lock);
NdisSetTimer(&pVc->DigitTimer,
pNdisTapiGatherDigits->ulFirstDigitTimeout);
}
//
// Set status to pending because this request just initiates the gathering of digits.
// The IRP will complete once all the digits come in.
//
Status = NDIS_STATUS_PENDING;
} while (FALSE);
DEREF_VC(pVc);
PXDEBUGP(PXD_LOUD, PXM_TAPI,
("PxTapiGatherDigits: Exit - Returning 0x%x\n", Status));
return (Status);
}
NDIS_STATUS
PxTapiMonitorDigits(
IN PNDISTAPI_REQUEST pNdisTapiRequest
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDIS_TAPI_MONITOR_DIGITS pNdisTapiMonitorDigits = NULL;
PPX_VC pVc = NULL;
PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Enter\n"));
pNdisTapiMonitorDigits =
(PNDIS_TAPI_MONITOR_DIGITS)pNdisTapiRequest->Data;
do {
if (!IsVcValid(pNdisTapiMonitorDigits->hdCall, &pVc)) {
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiMonitorDigits: Invalid call - Setting "
"Status NDISTAPIERR_BADDEVICEID\n"));
Status = NDISTAPIERR_BADDEVICEID;
break;
}
NdisAcquireSpinLock(&pVc->Lock);
if (pVc->PendingGatherDigits != NULL) {
//
// Can't monitor digits while a lineGatherDigits request is in effect.
//
NdisReleaseSpinLock(&pVc->Lock);
Status = NDIS_STATUS_FAILURE;
break;
}
if (pVc->ulMonitorDigitsModes != 0) {
NdisReleaseSpinLock(&pVc->Lock);
//
// We are already monitoring digits as a result of lineMonitorDigits request.
// If the digit modes in the this request are zero, then this is a request to
// cancel digit monitoring.
//
if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
Status = PxStopDigitReporting(pVc);
if (Status != NDIS_STATUS_SUCCESS) {
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiMonitorDigits: Failed to stop digit reporting with status 0x%x\n", Status));
break;
}
//
// It's a shame that I have to acquire and release again since I had
// the lock before, but there's no way to know whether I can set this
// to zero until I know the status that PxStopDigitReporting() returned.
//
NdisAcquireSpinLock(&pVc->Lock);
pVc->ulMonitorDigitsModes = 0;
NdisReleaseSpinLock(&pVc->Lock);
} else {
//
// We're already monitoring digits, so this request to do so must fail.
//
Status = NDIS_STATUS_FAILURE;
break;
}
} else {
PX_REQUEST ProxyRequest;
PNDIS_REQUEST NdisRequest;
pVc->ulMonitorDigitsModes = pNdisTapiMonitorDigits->ulDigitModes;
NdisReleaseSpinLock(&pVc->Lock);
if (pNdisTapiMonitorDigits->ulDigitModes == 0) {
//
// Someone's trying to cancel digit monitoring, but it hasn't been started yet.
//
Status = NDIS_STATUS_FAILURE;
break;
}
//
// Fill out our request structure to tell the miniport to start reporting digits.
//
NdisZeroMemory(&ProxyRequest, sizeof(ProxyRequest));
PxInitBlockStruc(&ProxyRequest.Block);
NdisRequest = &ProxyRequest.NdisRequest;
NdisRequest->RequestType =
NdisRequestSetInformation;
NdisRequest->DATA.SET_INFORMATION.Oid =
OID_CO_TAPI_REPORT_DIGITS;
NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
(PVOID)&pNdisTapiMonitorDigits->ulDigitModes;
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
sizeof(pNdisTapiMonitorDigits->ulDigitModes);
Status =
NdisCoRequest(pVc->Adapter->ClBindingHandle,
pVc->ClAf->NdisAfHandle,
pVc->ClVcHandle,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&ProxyRequest.Block);
}
if (Status != NDIS_STATUS_SUCCESS) {
NdisAcquireSpinLock(&pVc->Lock);
pVc->ulMonitorDigitsModes = 0;
NdisReleaseSpinLock(&pVc->Lock);
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxTapiMonitorDigits: NdisCoRequest to start digit reporting failed with status 0x%x\n", Status));
break;
}
}
} while (FALSE);
DEREF_VC(pVc);
PXDEBUGP(PXD_LOUD, PXM_TAPI, ("PxTapiMonitorDigits: Exit - Returning 0x%x\n", Status));
return (Status);
}
VOID
PxTapiCompleteDropIrps(
IN PPX_VC pVc,
IN ULONG Status
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: Vc %p\n", pVc));
ASSERT(!IsListEmpty(&pVc->PendingDropReqs));
ASSERT(pVc->Flags & PX_VC_DROP_PENDING);
while (!IsListEmpty(&pVc->PendingDropReqs)) {
PLIST_ENTRY Entry;
PIRP Irp;
KIRQL Irql;
PNDISTAPI_REQUEST pNdisTapiRequest;
Entry =
RemoveHeadList(&pVc->PendingDropReqs);
NdisReleaseSpinLock(&pVc->Lock);
pNdisTapiRequest =
CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
Irp = pNdisTapiRequest->Irp;
ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
IoSetCancelRoutine(Irp, NULL);
Irp->IoStatus.Information =
sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
Irp->IoStatus.Status = STATUS_SUCCESS;
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
IoCompleteRequest(Irp, IO_NO_INCREMENT);
NdisAcquireSpinLock(&pVc->Lock);
}
pVc->Flags &= ~PX_VC_DROP_PENDING;
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteDropIrps: exit\n"));
return;
}
VOID
PxTapiCompleteAllIrps(
IN PPX_VC pVc,
IN ULONG Status
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: Vc %p\n", pVc));
while (!IsListEmpty(&pVc->PendingDropReqs)) {
PLIST_ENTRY Entry;
PIRP Irp;
KIRQL Irql;
PNDISTAPI_REQUEST pNdisTapiRequest;
Entry =
RemoveHeadList(&pVc->PendingDropReqs);
NdisReleaseSpinLock(&pVc->Lock);
pNdisTapiRequest =
CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
Irp = pNdisTapiRequest->Irp;
ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
IoSetCancelRoutine(Irp, NULL);
Irp->IoStatus.Information =
sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
Irp->IoStatus.Status = STATUS_SUCCESS;
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
IoCompleteRequest(Irp, IO_NO_INCREMENT);
NdisAcquireSpinLock(&pVc->Lock);
}
pVc->Flags &= ~PX_VC_DROP_PENDING;
if (pVc->PendingGatherDigits != NULL) {
PIRP Irp;
KIRQL Irql;
PNDISTAPI_REQUEST pNdisTapiRequest;
pNdisTapiRequest = pVc->PendingGatherDigits;
pVc->PendingGatherDigits = NULL;
NdisReleaseSpinLock(&pVc->Lock);
Irp = pNdisTapiRequest->Irp;
ASSERT(pNdisTapiRequest == Irp->AssociatedIrp.SystemBuffer);
IoSetCancelRoutine(Irp, NULL);
Irp->IoStatus.Information =
sizeof(NDISTAPI_REQUEST) + (pNdisTapiRequest->ulDataSize - 1);
Irp->IoStatus.Status = STATUS_SUCCESS;
PXDEBUGP (PXD_LOUD, PXM_TAPI,
("PxTapiCompleteIrp: Irp %p, Oid: %x\n", Irp, pNdisTapiRequest->Oid));
IoCompleteRequest(Irp, IO_NO_INCREMENT);
NdisAcquireSpinLock(&pVc->Lock);
}
PXDEBUGP (PXD_LOUD, PXM_TAPI, ("PxTapiCompleteAllIrps: exit\n"));
return;
}
VOID
PxIndicateStatus(
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
/*++
Routine Description:
Called to send any event info that may be in the device extension to TAPI in the form of an
NDIS_TAPI_EVENT, sent in an available queued GET_EVENT IRP. If there's no outstanding IRP, stick
the data in the queue so it will go whenver there is one.
Arguments:
Return Value:
--*/
{
PIRP Irp;
PNDIS_TAPI_EVENT NdisTapiEvent;
PNDISTAPI_EVENT_DATA NdisTapiEventData;
NdisTapiEvent = StatusBuffer;
//
// Sync event buf access by acquiring EventSpinLock
//
NdisAcquireSpinLock(&TspCB.Lock);
//
// Are we initialized with TAPI?
//
if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
PXDEBUGP(PXD_WARNING, PXM_TAPI,
("PxIndicateStatus: TAPI not connected!\n"));
NdisReleaseSpinLock(&TspCB.Lock);
return;
}
NdisReleaseSpinLock(&TspCB.Lock);
NdisAcquireSpinLock(&TspEventList.Lock);
Irp = TspEventList.RequestIrp;
TspEventList.RequestIrp = NULL;
if (Irp == NULL) {
PPROVIDER_EVENT ProviderEvent;
ProviderEvent =
ExAllocateFromNPagedLookasideList(&ProviderEventLookaside);
if (ProviderEvent != NULL) {
RtlMoveMemory(&ProviderEvent->Event,
StatusBuffer,
sizeof(NDIS_TAPI_EVENT));
InsertTailList(&TspEventList.List,
&ProviderEvent->Linkage);
TspEventList.Count++;
if (TspEventList.Count > TspEventList.MaxCount) {
TspEventList.MaxCount = TspEventList.Count;
}
}
} else {
ASSERT(IsListEmpty(&TspEventList.List));
}
NdisReleaseSpinLock(&TspEventList.Lock);
//
// Check of there is an outstanding request to satisfy
//
if (Irp != NULL) {
KIRQL Irql;
//
// Clear out the cancel routine
//
IoSetCancelRoutine (Irp, NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information =
sizeof(NDISTAPI_EVENT_DATA) + StatusBufferSize - 1;
//
// Copy as much of the input data possible from the input data
// queue to the SystemBuffer to satisfy the read.
//
NdisTapiEventData = Irp->AssociatedIrp.SystemBuffer;
ASSERT(NdisTapiEventData->ulTotalSize >= StatusBufferSize);
RtlMoveMemory(NdisTapiEventData->Data,
(PCHAR) StatusBuffer,
StatusBufferSize);
//
// Set the flag so that we start the next packet and complete
// this read request (with STATUS_SUCCESS) prior to return.
//
NdisTapiEventData->ulUsedSize = StatusBufferSize;
PXDEBUGP(PXD_LOUD, PXM_TAPI,
("PxIndicateStatus: htLine: %x, htCall: %x, Msg: %x\n",
NdisTapiEvent->htLine, NdisTapiEvent->htCall, NdisTapiEvent->ulMsg));
PXDEBUGP(PXD_LOUD, PXM_TAPI,
(" : p1: %x, p2: %x, p3: %x\n",
NdisTapiEvent->ulParam1, NdisTapiEvent->ulParam2, NdisTapiEvent->ulParam3));
IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
}
}
NDIS_STATUS
AllocateTapiResources(
IN PPX_ADAPTER ClAdapter,
IN PPX_CL_AF pClAf
)
{
NDIS_STATUS Status;
ULONG SizeNeeded;
ULONG TapiVersion;
PPX_TAPI_LINE TapiLine = NULL;
PPX_TAPI_ADDR TapiAddr = NULL;
UINT i, j;
PPX_TAPI_PROVIDER TapiProvider;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiResoures: Enter\n"));
//
// See if this device supports TAPI and if so
// see how many lines it has
//
TapiProvider =
AllocateTapiProvider(ClAdapter, pClAf);
if (TapiProvider == NULL) {
PXDEBUGP(PXD_ERROR, PXM_TAPI, ("Error allocating TapiProvider!\n"));
return (NDIS_STATUS_FAILURE);
}
return (NDIS_STATUS_SUCCESS);
}
PPX_TAPI_PROVIDER
AllocateTapiProvider(
PPX_ADAPTER ClAdapter,
PPX_CL_AF pClAf
)
{
PNDIS_REQUEST NdisRequest;
NDIS_STATUS Status;
CO_TAPI_CM_CAPS CmCaps;
BOOLEAN TapiSupported = TRUE;
ULONG AllocSize;
PTAPI_LINE_TABLE LineTable;
PPX_TAPI_PROVIDER TapiProvider = NULL;
ULONG i;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("AllocateTapiProvider: Enter\n"));
do {
PX_REQUEST ProxyRequest;
PPX_REQUEST pProxyRequest = &ProxyRequest;
NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
NdisZeroMemory(&CmCaps, sizeof(CmCaps));
PxInitBlockStruc (&pProxyRequest->Block);
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestQueryInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_CO_TAPI_CM_CAPS;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
&CmCaps;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(CmCaps);
Status =
NdisCoRequest(ClAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&pProxyRequest->Block);
}
if (Status != NDIS_STATUS_SUCCESS) {
if (Status != NDIS_STATUS_NOT_SUPPORTED) {
break;
}
Status = NDIS_STATUS_SUCCESS;
//
// Setup a default config for this device.
// ToDo! These values should be read from
// the registry on a per device basis!
//
CmCaps.ulNumLines = 1;
CmCaps.ulFlags = 0;
CmCaps.ulCoTapiVersion = CO_TAPI_VERSION;
TapiSupported = FALSE;
}
//
// Allocate a tapi provider block for this adapter
// The provider block will live outside of the
// adapter. This allows us to continue tapi service
// after a machine has been power managed.
//
AllocSize = sizeof(PX_TAPI_PROVIDER) +
(sizeof(PPX_TAPI_LINE) * CmCaps.ulNumLines) +
sizeof(PVOID);
PxAllocMem(TapiProvider, AllocSize, PX_PROVIDER_TAG);
if (TapiProvider == NULL) {
break;
}
NdisZeroMemory(TapiProvider, AllocSize);
NdisAllocateSpinLock(&TapiProvider->Lock);
TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
TapiProvider->Adapter = ClAdapter;
TapiProvider->ClAf = pClAf;
TapiProvider->NumDevices = CmCaps.ulNumLines;
TapiProvider->Guid = ClAdapter->Guid;
TapiProvider->Af = pClAf->Af;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider Allocated: GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
TapiProvider->Guid.Data1, TapiProvider->Guid.Data2, TapiProvider->Guid.Data3,
TapiProvider->Guid.Data4[0],TapiProvider->Guid.Data4[1],TapiProvider->Guid.Data4[2],
TapiProvider->Guid.Data4[3],TapiProvider->Guid.Data4[4],TapiProvider->Guid.Data4[5],
TapiProvider->Guid.Data4[6],TapiProvider->Guid.Data4[7]));
TapiProvider->TapiSupported = TapiSupported;
TapiProvider->TapiFlags |= CmCaps.ulFlags;
TapiProvider->CoTapiVersion = CmCaps.ulCoTapiVersion;
InitializeListHead(&TapiProvider->LineList);
InitializeListHead(&TapiProvider->CreateList);
for (i = 0; i < TapiProvider->NumDevices; i++) {
PPX_TAPI_LINE TapiLine;
TapiLine =
AllocateTapiLine(TapiProvider, i);
if (TapiLine == NULL) {
FreeTapiProvider(TapiProvider);
TapiProvider = NULL;
break;
}
//
// Put the new line on the create list
// We will need to insert it in the line table
// and possibly notify tapi about it
//
InsertTailList(&TapiProvider->CreateList, &TapiLine->Linkage);
}
} while ( FALSE );
if (TapiProvider != NULL) {
PPX_TAPI_PROVIDER tp;
BOOLEAN TapiConnected;
//
// See if we already have a provider for this
// GUID. If we don't just add this provider on
// to the tsp and do the right thing with it's
// new lines. If we do see if anything on the
// provider has changed and do the right thing
// with it's tapi lines.
//
NdisAcquireSpinLock(&TspCB.Lock);
tp = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
while ((PVOID)tp != (PVOID)&TspCB.ProviderList) {
if ((tp->Status == PROVIDER_STATUS_OFFLINE) &&
(NdisEqualMemory(&tp->Guid, &TapiProvider->Guid, sizeof(tp->Guid))) &&
(pClAf->Af.AddressFamily == tp->Af.AddressFamily)) {
//
// We have already have a provider for this
// adapter/address family. See if anything has
// changed.
//
//
// ToDo!
// This check needs to be more complete!
//
if (tp->NumDevices != TapiProvider->NumDevices) {
//
// ToDo!
// Much work to do here!
//
} else {
//
// Nothing has changed so free the new allocations
// and reactivate the old ones.
//
FreeTapiProvider(TapiProvider);
TapiProvider = tp;
}
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider found: GUID %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x\n",
ClAdapter->Guid.Data1, ClAdapter->Guid.Data2, ClAdapter->Guid.Data3,
ClAdapter->Guid.Data4[0],ClAdapter->Guid.Data4[1],ClAdapter->Guid.Data4[2],
ClAdapter->Guid.Data4[3],ClAdapter->Guid.Data4[4],ClAdapter->Guid.Data4[5],
ClAdapter->Guid.Data4[6],ClAdapter->Guid.Data4[7]));
break;
} else {
tp = (PPX_TAPI_PROVIDER)tp->Linkage.Flink;
}
}
//
// We did not find a provider on the list
// so insert the new provider
//
if ((PVOID)tp == (PVOID)&TspCB.ProviderList) {
InsertTailList(&TspCB.ProviderList, &TapiProvider->Linkage);
TspCB.NdisTapiNumDevices += TapiProvider->NumDevices;
}
if (TspCB.Status == NDISTAPI_STATUS_CONNECTED) {
TapiProvider->Status = PROVIDER_STATUS_ONLINE;
}
NdisReleaseSpinLock(&TspCB.Lock);
NdisAcquireSpinLock(&TapiProvider->Lock);
pClAf->TapiProvider = TapiProvider;
TapiProvider->ClAf= pClAf;
TapiProvider->Adapter = ClAdapter;
while (!IsListEmpty(&TapiProvider->CreateList)) {
PPX_TAPI_LINE TapiLine;
TapiLine = (PPX_TAPI_LINE)
RemoveHeadList(&TapiProvider->CreateList);
InsertTailList(&TapiProvider->LineList, &TapiLine->Linkage);
//
// Insert the line in the table
//
if (!InsertLineInTable(TapiLine)) {
FreeTapiLine(TapiLine);
continue;
}
NdisReleaseSpinLock(&TapiProvider->Lock);
SendTapiLineCreate(TapiLine);
NdisAcquireSpinLock(&TapiProvider->Lock);
}
MarkProviderOnline(TapiProvider);
NdisReleaseSpinLock(&TapiProvider->Lock);
}
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("TapiProvider: %x\n", TapiProvider));
return (TapiProvider);
}
VOID
MarkProviderOffline(
PPX_TAPI_PROVIDER TapiProvider
)
{
LOCK_STATE LockState;
ULONG i;
TapiProvider->Status = PROVIDER_STATUS_OFFLINE;
TapiProvider->ClAf = NULL;
TapiProvider->Adapter = NULL;
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE TapiLine;
TapiLine = LineTable.Table[i];
if (TapiLine != NULL) {
NdisAcquireSpinLock(&TapiLine->Lock);
if (TapiLine->TapiProvider == TapiProvider) {
TapiLine->DevStatus->ulDevStatusFlags &=
~(LINEDEVSTATUSFLAGS_INSERVICE);
TapiLine->ClAf = NULL;
NdisReleaseSpinLock(&TapiLine->Lock);
#if 0
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
SendTapiLineClose(TapiLine);
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
#endif
} else {
NdisReleaseSpinLock(&TapiLine->Lock);
}
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
}
VOID
MarkProviderOnline(
PPX_TAPI_PROVIDER TapiProvider
)
{
LOCK_STATE LockState;
ULONG i;
TapiProvider->Status = PROVIDER_STATUS_ONLINE;
NdisReleaseSpinLock(&TapiProvider->Lock);
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE TapiLine;
TapiLine = LineTable.Table[i];
if (TapiLine != NULL) {
NdisAcquireSpinLock(&TapiLine->Lock);
if (TapiLine->TapiProvider == TapiProvider) {
TapiLine->DevStatus->ulDevStatusFlags |=
LINEDEVSTATUSFLAGS_INSERVICE;
TapiLine->ClAf = TapiProvider->ClAf;
//#if 0
//
// This line was open by tapi before it was
// marked offline. We need to force tapi to
// reopen the line so we will send the CLOSE_LINE
// message in the hopes that any apps that care
// will then turn around and reopen the line.
//
if (TapiLine->DevStatus->ulNumOpens != 0) {
// TapiLine->DevStatus->ulNumOpens = 0;
NdisReleaseSpinLock(&TapiLine->Lock);
SendTapiLineClose(TapiLine);
NdisAcquireSpinLock(&TapiLine->Lock);
}
//#endif
}
NdisReleaseSpinLock(&TapiLine->Lock);
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
NdisAcquireSpinLock(&TapiProvider->Lock);
}
VOID
MarkProviderConnected(
PPX_TAPI_PROVIDER TapiProvider
)
{
LOCK_STATE LockState;
ULONG i;
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE TapiLine;
TapiLine = LineTable.Table[i];
if (TapiLine != NULL) {
NdisAcquireSpinLock(&TapiLine->Lock);
if (TapiLine->TapiProvider == TapiProvider) {
TapiLine->DevStatus->ulDevStatusFlags |=
LINEDEVSTATUSFLAGS_CONNECTED;
}
NdisReleaseSpinLock(&TapiLine->Lock);
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
}
VOID
MarkProviderDisconnected(
PPX_TAPI_PROVIDER TapiProvider
)
{
LOCK_STATE LockState;
ULONG i;
//
// ToDo! If we have any active calls on this line we
// need to disconnect them without tapi's assistance. This
// would only happen if tapi crashes while we have active calls
//
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE TapiLine;
TapiLine = LineTable.Table[i];
if (TapiLine != NULL) {
NdisAcquireSpinLock(&TapiLine->Lock);
if (TapiLine->TapiProvider == TapiProvider) {
TapiLine->DevStatus->ulDevStatusFlags &=
~(LINEDEVSTATUSFLAGS_CONNECTED);
}
NdisReleaseSpinLock(&TapiLine->Lock);
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
}
VOID
ClearSapWithTapiLine(
PPX_CL_SAP pClSap
)
{
LOCK_STATE LockState;
ULONG i;
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE TapiLine;
TapiLine = LineTable.Table[i];
if (TapiLine != NULL) {
NdisAcquireSpinLock(&TapiLine->Lock);
if (TapiLine->ClSap == pClSap) {
TapiLine->ClSap = NULL;
}
NdisReleaseSpinLock(&TapiLine->Lock);
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
}
VOID
FreeTapiProvider(
PPX_TAPI_PROVIDER TapiProvider
)
{
//
// Free any lines on the create list
//
while (!IsListEmpty(&TapiProvider->CreateList)) {
PPX_TAPI_LINE TapiLine;
TapiLine = (PPX_TAPI_LINE)
RemoveHeadList(&TapiProvider->CreateList);
FreeTapiLine(TapiLine);
}
//
// Free the lines associated with this provider
//
while (!IsListEmpty(&TapiProvider->LineList)) {
PPX_TAPI_LINE TapiLine;
TapiLine = (PPX_TAPI_LINE)
RemoveHeadList(&TapiProvider->LineList);
if (TapiLine->Flags & PX_LINE_IN_TABLE) {
RemoveTapiLineFromTable(TapiLine);
}
FreeTapiLine(TapiLine);
}
NdisFreeSpinLock(&TapiProvider->Lock);
PxFreeMem(TapiProvider);
}
PPX_TAPI_LINE
AllocateTapiLine(
PPX_TAPI_PROVIDER TapiProvider,
ULONG LineNumber
)
{
PLINE_DEV_CAPS ldc, ldc1;
PNDIS_REQUEST NdisRequest;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PCO_TAPI_LINE_CAPS LineCaps;
PUCHAR EnumBuffer;
#if DBG
ULONG EnumBufferSize = PAGE_SIZE -
sizeof(PXD_ALLOCATION);
#else
ULONG EnumBufferSize = PAGE_SIZE;
#endif
ULONG SizeNeeded, SizeDevCaps;
PPX_TAPI_LINE TapiLine = NULL;
PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
PPX_CL_AF pClAf = TapiProvider->ClAf;
ULONG i;
PX_REQUEST ProxyRequest;
PPX_REQUEST pProxyRequest = &ProxyRequest;
PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
if (EnumBuffer == NULL) {
return (NULL);
}
NdisZeroMemory(EnumBuffer, EnumBufferSize);
LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
LineCaps->ulLineID = LineNumber;
ldc = &LineCaps->LineDevCaps;
ldc->ulTotalSize =
EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
//
// If this device does not support TAPI we will build
// a default line configuration.
// ToDo! Some of these values should be queried from
// the registry on a per device basis!
//
if (!TapiProvider->TapiSupported) {
NDIS_CO_LINK_SPEED SpeedInfo;
LineCaps->ulFlags = 0;
ldc->ulTotalSize =
ldc->ulNeededSize =
ldc->ulUsedSize =
sizeof(LINE_DEV_CAPS);
ldc->ulStringFormat = STRINGFORMAT_ASCII;
ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
ldc->ulNumAddresses = 1;
ldc->ulBearerModes = LINEBEARERMODE_VOICE |
LINEBEARERMODE_DATA;
ldc->ulMediaModes = LINEMEDIAMODE_DIGITALDATA;
ldc->ulMaxNumActiveCalls = 1000;
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
PxInitBlockStruc (&pProxyRequest->Block);
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestQueryInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_GEN_CO_LINK_SPEED;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
&SpeedInfo;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
sizeof(NDIS_CO_LINK_SPEED);
PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: DeviceExtension->RegistryFlags = %x\n", DeviceExtension->RegistryFlags));
PXDEBUGP(PXD_INFO, PXM_CO, ("NDProxy: using ndisrequest to get rates from adapter\n"));
Status =
NdisCoRequest(ClAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&pProxyRequest->Block);
}
if (Status == NDIS_STATUS_SUCCESS) {
ldc->ulMaxRate = SpeedInfo.Outbound;
} else {
ldc->ulMaxRate = 128000;
}
} else if (!(TapiProvider->TapiFlags & CO_TAPI_FLAG_PER_LINE_CAPS) &&
(LineNumber > 0)) {
PLINE_DEV_CAPS ldc1;
PCO_TAPI_LINE_CAPS LineCaps1;
PPX_TAPI_LINE Line1;
//
// If all of the lines on this device have the same caps
// and this is not the first line, just copy the caps
// from the first line!
//
Line1 = (PPX_TAPI_LINE)
TapiProvider->CreateList.Flink;
ldc1 = Line1->DevCaps;
if (ldc1->ulTotalSize > ldc->ulTotalSize) {
//
// We don't have enough memory allocated!
//
PxFreeMem(EnumBuffer);
EnumBufferSize =
(sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS) +
ldc1->ulTotalSize);
PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
if (EnumBuffer == NULL){
return (NULL);
}
NdisZeroMemory(EnumBuffer, EnumBufferSize);
LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
LineCaps->ulLineID = LineNumber;
LineCaps->LineDevCaps.ulTotalSize =
EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) -
sizeof(LINE_DEV_CAPS));
ldc = &LineCaps->LineDevCaps;
}
NdisMoveMemory(ldc, ldc1, ldc1->ulUsedSize);
} else {
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
PxInitBlockStruc (&pProxyRequest->Block);
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestQueryInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_CO_TAPI_LINE_CAPS;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
LineCaps;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
EnumBufferSize;
Status =
NdisCoRequest(ClAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING) {
Status = PxBlock(&pProxyRequest->Block);
}
if (Status == NDIS_STATUS_INVALID_LENGTH){
ULONG SizeNeeded;
//
// Our buffer was not large enough so try again
//
SizeNeeded =
EnumBufferSize =
MAX (LineCaps->LineDevCaps.ulNeededSize,
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
PxFreeMem(EnumBuffer);
PxAllocMem((PCO_TAPI_LINE_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMLINE_TAG);
if (EnumBuffer == NULL){
return(NULL);
}
NdisZeroMemory(EnumBuffer, EnumBufferSize);
LineCaps = (PCO_TAPI_LINE_CAPS)EnumBuffer;
LineCaps->ulLineID = LineNumber;
ldc = &LineCaps->LineDevCaps;
ldc->ulTotalSize =
EnumBufferSize - (sizeof(CO_TAPI_LINE_CAPS) - sizeof(LINE_DEV_CAPS));
NdisZeroMemory(pProxyRequest, sizeof(PX_REQUEST));
PxInitBlockStruc (&pProxyRequest->Block);
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestQueryInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_CO_TAPI_LINE_CAPS;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
LineCaps;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
EnumBufferSize;
Status =
NdisCoRequest(ClAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING){
Status = PxBlock(&pProxyRequest->Block);
}
if (Status != NDIS_STATUS_SUCCESS){
PxFreeMem(EnumBuffer);
return(NULL);
}
}else if (Status != STATUS_SUCCESS){
PxFreeMem(EnumBuffer);
return(NULL);
}
}
SizeNeeded = sizeof(PX_TAPI_LINE);
SizeNeeded +=
(sizeof(PPX_TAPI_ADDR) * LineCaps->LineDevCaps.ulNumAddresses);
SizeNeeded += sizeof(LINE_DEV_STATUS);
SizeNeeded += 3*sizeof(PVOID);
if (LineCaps->LineDevCaps.ulUsedSize < sizeof(LINE_DEV_CAPS)) {
LineCaps->LineDevCaps.ulUsedSize = sizeof(LINE_DEV_CAPS);
}
SizeDevCaps = LineCaps->LineDevCaps.ulUsedSize;
SizeNeeded += SizeDevCaps;
PxAllocMem(TapiLine, SizeNeeded, PX_TAPILINE_TAG);
if (TapiLine == NULL){
PxFreeMem(EnumBuffer);
return(NULL);
}
NdisZeroMemory(TapiLine, SizeNeeded);
TapiLine->DevCaps = (PLINE_DEV_CAPS)
((PUCHAR)TapiLine + sizeof(PX_TAPI_LINE) + sizeof(PVOID));
(ULONG_PTR)TapiLine->DevCaps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
TapiLine->DevStatus = (PLINE_DEV_STATUS)
((PUCHAR)TapiLine->DevCaps + SizeDevCaps + sizeof(PVOID));
(ULONG_PTR)TapiLine->DevStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
TapiLine->AddrTable.Table = (PPX_TAPI_ADDR*)
((PUCHAR)TapiLine->DevStatus +
sizeof(LINE_DEV_STATUS) + sizeof(PVOID));
(ULONG_PTR)TapiLine->AddrTable.Table &= ~((ULONG_PTR)sizeof(PVOID) - 1);
NdisMoveMemory(TapiLine->DevCaps,
&LineCaps->LineDevCaps,
LineCaps->LineDevCaps.ulUsedSize);
ldc = TapiLine->DevCaps;
//
// Proxy fills some fields on behalf of all cm/miniports
//
ldc->ulPermanentLineID =
TapiProvider->Guid.Data1 + LineNumber;
ldc->ulAddressModes = LINEADDRESSMODE_ADDRESSID;
ldc->ulAnswerMode = LINEANSWERMODE_NONE;
ldc->ulLineStates = LINEDEVSTATE_CONNECTED |
LINEDEVSTATE_DISCONNECTED |
LINEDEVSTATE_OPEN |
LINEDEVSTATE_CLOSE |
LINEDEVSTATE_INSERVICE |
LINEDEVSTATE_OUTOFSERVICE |
LINEDEVSTATE_REMOVED;
ldc->ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP;
ldc->PermanentLineGuid = TapiProvider->Guid;
ldc->ulTotalSize =
ldc->ulNeededSize =
ldc->ulUsedSize;
TapiLine->TapiProvider = TapiProvider;
TapiLine->CmLineID = LineNumber;
TapiLine->Flags |= LineCaps->ulFlags;
TapiLine->DevStatus->ulTotalSize =
TapiLine->DevStatus->ulNeededSize =
TapiLine->DevStatus->ulUsedSize = sizeof(LINE_DEV_STATUS);
TapiLine->ClAf = pClAf;
TapiLine->RefCount= 1;
//
// Build the address table for this line
//
InitializeListHead(&TapiLine->AddrTable.List);
NdisAllocateSpinLock(&TapiLine->Lock);
TapiLine->AddrTable.Size = TapiLine->DevCaps->ulNumAddresses;
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("Allocated TapiLine %p LineId %d \n", TapiLine, TapiLine->CmLineID));
for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++) {
PPX_TAPI_ADDR TapiAddr;
TapiAddr =
AllocateTapiAddr(TapiProvider, TapiLine, i);
if (TapiAddr == NULL) {
FreeTapiLine(TapiLine);
TapiLine = NULL;
break;
}
//
// Insert the address in the line's address table
//
TapiLine->AddrTable.Table[i] = TapiAddr;
InsertTailList(&TapiLine->AddrTable.List,
&TapiAddr->Linkage);
TapiLine->AddrTable.Count++;
}
PxFreeMem(EnumBuffer);
return (TapiLine);
}
VOID
FreeTapiLine(
PPX_TAPI_LINE TapiLine
)
{
ULONG i;
for (i = 0; i < TapiLine->DevCaps->ulNumAddresses; i++){
PPX_TAPI_ADDR TapiAddr;
//
// Remove the address from the line table
//
TapiAddr = TapiLine->AddrTable.Table[i];
if (TapiAddr != NULL) {
RemoveEntryList(&TapiAddr->Linkage);
TapiLine->AddrTable.Table[i] = NULL;
TapiLine->AddrTable.Count--;
//
// Free the address memory
//
FreeTapiAddr(TapiAddr);
}
}
NdisFreeSpinLock(&TapiLine->Lock);
//
// Free the line memory
//
PxFreeMem(TapiLine);
}
PPX_TAPI_ADDR
AllocateTapiAddr(
PPX_TAPI_PROVIDER TapiProvider,
PPX_TAPI_LINE TapiLine,
ULONG AddrID
)
{
PPX_TAPI_ADDR TapiAddr;
PUCHAR EnumBuffer;
#if DBG
ULONG EnumBufferSize = PAGE_SIZE -
sizeof(PXD_ALLOCATION);
#else
ULONG EnumBufferSize = PAGE_SIZE;
#endif
PNDIS_REQUEST NdisRequest;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG SizeNeeded;
PPX_ADAPTER ClAdapter = TapiProvider->Adapter;
PPX_CL_AF pClAf = TapiProvider->ClAf;
PX_REQUEST ProxyRequest;
PPX_REQUEST pProxyRequest = &ProxyRequest;
PLINE_ADDRESS_CAPS ac;
PCO_TAPI_ADDRESS_CAPS AddrCaps;
PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
if (EnumBuffer == NULL){
return(NULL);
}
NdisZeroMemory(EnumBuffer, EnumBufferSize);
AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
AddrCaps->ulLineID = TapiLine->CmLineID;
AddrCaps->ulAddressID = AddrID;
ac = &AddrCaps->LineAddressCaps;
ac->ulTotalSize =
EnumBufferSize - (sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
//
// If this device does not support TAPI we will
// build a default address.
// ToDo! Some of these values should be queried from
// the registry on a per device basis!
//
if (!TapiProvider->TapiSupported){
ac->ulTotalSize =
ac->ulNeededSize =
ac->ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
ac->ulMaxNumActiveCalls = 1000;
}else if (!(TapiLine->Flags & CO_TAPI_FLAG_PER_ADDRESS_CAPS) &&
(AddrID > 0)){
PLINE_ADDRESS_CAPS ac1;
PCO_TAPI_ADDRESS_CAPS AddrCaps1;
PPX_TAPI_ADDR Addr1;
//
// If all of the addresses on this line have the same
// caps and this is not the first address, just copy
// the caps from the first address!
//
Addr1 = (PPX_TAPI_ADDR)
TapiLine->AddrTable.List.Flink;
ac1 = Addr1->Caps;
if (ac1->ulTotalSize > ac->ulTotalSize){
//
// We don't have enough memory allocated!
//
PxFreeMem(EnumBuffer);
EnumBufferSize =
(sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS) +
ac1->ulTotalSize);
PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
if (EnumBuffer == NULL){
return (NULL);
}
NdisZeroMemory(EnumBuffer, EnumBufferSize);
AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
AddrCaps->ulLineID = TapiLine->CmLineID;
AddrCaps->ulAddressID = AddrID;
AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
(sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
}
ac = &AddrCaps->LineAddressCaps;
NdisMoveMemory(ac, ac1, ac1->ulUsedSize);
}else{
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
PxInitBlockStruc (&pProxyRequest->Block);
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestQueryInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_CO_TAPI_ADDRESS_CAPS;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
AddrCaps;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
EnumBufferSize;
Status =
NdisCoRequest(ClAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING){
Status = PxBlock(&pProxyRequest->Block);
}
if (Status == NDIS_STATUS_INVALID_LENGTH){
//
// Our buffer was not large enough so try again
//
SizeNeeded =
EnumBufferSize =
NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
PxFreeMem(EnumBuffer);
PxAllocMem((PCO_TAPI_ADDRESS_CAPS)EnumBuffer, EnumBufferSize, PX_ENUMADDR_TAG);
if (EnumBuffer == NULL){
return(NULL);
}
NdisZeroMemory(EnumBuffer, EnumBufferSize);
AddrCaps = (PCO_TAPI_ADDRESS_CAPS)EnumBuffer;
AddrCaps->ulLineID = TapiLine->CmLineID;
AddrCaps->ulAddressID = AddrID;
AddrCaps->LineAddressCaps.ulTotalSize = EnumBufferSize -
(sizeof(CO_TAPI_ADDRESS_CAPS) - sizeof(LINE_ADDRESS_CAPS));
NdisZeroMemory(pProxyRequest, sizeof(ProxyRequest));
PxInitBlockStruc (&pProxyRequest->Block);
NdisRequest = &pProxyRequest->NdisRequest;
NdisRequest->RequestType =
NdisRequestQueryInformation;
NdisRequest->DATA.QUERY_INFORMATION.Oid =
OID_CO_TAPI_ADDRESS_CAPS;
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
AddrCaps;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
EnumBufferSize;
Status =
NdisCoRequest(ClAdapter->ClBindingHandle,
pClAf->NdisAfHandle,
NULL,
NULL,
NdisRequest);
if (Status == NDIS_STATUS_PENDING){
Status = PxBlock(&pProxyRequest->Block);
}
if (Status != NDIS_STATUS_SUCCESS){
PxFreeMem(EnumBuffer);
return(NULL);
}
}else if (Status != STATUS_SUCCESS){
PxFreeMem(EnumBuffer);
return(NULL);
}
}
if (AddrCaps->LineAddressCaps.ulUsedSize < sizeof(LINE_ADDRESS_CAPS)) {
AddrCaps->LineAddressCaps.ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
}
SizeNeeded = sizeof(PX_TAPI_ADDR);
SizeNeeded += AddrCaps->LineAddressCaps.ulUsedSize;
SizeNeeded += sizeof(LINE_ADDRESS_STATUS);
SizeNeeded += 2*sizeof(PVOID);
PxAllocMem(TapiAddr, SizeNeeded, PX_TAPIADDR_TAG);
if (TapiAddr == NULL){
PxFreeMem(EnumBuffer);
return (NULL);
}
NdisZeroMemory((PUCHAR)TapiAddr, SizeNeeded);
TapiAddr->Caps = (PLINE_ADDRESS_CAPS)
((PUCHAR)TapiAddr + sizeof(PX_TAPI_ADDR) + sizeof(PVOID));
(ULONG_PTR)TapiAddr->Caps &= ~((ULONG_PTR)sizeof(PVOID) - 1);
TapiAddr->AddrStatus = (PLINE_ADDRESS_STATUS)
((PUCHAR)TapiAddr->Caps +
AddrCaps->LineAddressCaps.ulUsedSize + sizeof(PVOID));
(ULONG_PTR)TapiAddr->AddrStatus &= ~((ULONG_PTR)sizeof(PVOID) - 1);
NdisMoveMemory(TapiAddr->Caps,
&AddrCaps->LineAddressCaps,
AddrCaps->LineAddressCaps.ulUsedSize);
//
// Proxy fills some fields on behalf of all cm/miniports
//
ac = TapiAddr->Caps;
if (ac->ulTotalSize < ac->ulUsedSize) {
ac->ulTotalSize = ac->ulUsedSize;
}
if (ac->ulNeededSize < ac->ulNeededSize) {
ac->ulNeededSize = ac->ulUsedSize;
}
ac->ulLineDeviceID = TapiLine->ulDeviceID;
ac->ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
ac->ulAddressStates = LINEADDRESSSTATE_NUMCALLS;
ac->ulCallInfoStates = LINECALLINFOSTATE_BEARERMODE |
LINECALLINFOSTATE_RATE |
LINECALLINFOSTATE_MEDIAMODE;
ac->ulCallStates = LINECALLSTATE_IDLE |
LINECALLSTATE_OFFERING |
LINECALLSTATE_ACCEPTED |
LINECALLSTATE_BUSY |
LINECALLSTATE_CONNECTED |
LINECALLSTATE_PROCEEDING |
LINECALLSTATE_DISCONNECTED;
ac->ulDialToneModes = 0;
ac->ulBusyModes = LINEBUSYMODE_UNAVAIL;
ac->ulSpecialInfo = 0;
ac->ulDisconnectModes = LINEDISCONNECTMODE_NORMAL |
LINEDISCONNECTMODE_BUSY |
LINEDISCONNECTMODE_NOANSWER;
TapiAddr->TapiLine = TapiLine;
TapiAddr->AddrId = AddrID;
PxFreeMem(EnumBuffer);
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Allocated TapiAddr %p AddrId %d for TapiLine %p\n", TapiAddr, TapiAddr->AddrId, TapiLine));
return (TapiAddr);
}
VOID
FreeTapiAddr(
PPX_TAPI_ADDR TapiAddr
)
{
//
// ToDo! we need to tear down all
// active calls on this address.
//
PxFreeMem(TapiAddr);
}
NDIS_STATUS
AllocateTapiCallInfo(
PPX_VC pVc,
LINE_CALL_INFO UNALIGNED *LineCallInfo
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
ULONG SizeNeeded;
if (pVc->CallInfo) {
PxFreeMem(pVc->CallInfo);
}
if (LineCallInfo != NULL) {
SizeNeeded = LineCallInfo->ulUsedSize;
} else {
SizeNeeded = sizeof(LINE_CALL_INFO) + LINE_CALL_INFO_VAR_DATA_SIZE;
}
PxAllocMem(pVc->CallInfo, SizeNeeded, PX_LINECALLINFO_TAG);
if (pVc->CallInfo == NULL) {
return (NDIS_STATUS_RESOURCES);
}
pVc->ulCallInfoFieldsChanged = 0;
NdisZeroMemory(pVc->CallInfo, SizeNeeded);
if (LineCallInfo != NULL) {
NdisMoveMemory(pVc->CallInfo,
LineCallInfo,
LineCallInfo->ulUsedSize);
} else {
pVc->CallInfo->ulTotalSize = SizeNeeded;
pVc->CallInfo->ulNeededSize = SizeNeeded;
pVc->CallInfo->ulUsedSize = sizeof(LINE_CALL_INFO);
}
return (Status);
}
BOOLEAN
InsertVcInTable(
PPX_VC pVc
)
{
ULONG i;
ULONG index;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PUCHAR AllocatedMemory;
LOCK_STATE LockState;
PPX_CL_AF pClAf;
NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
if (VcTable.Count == VcTable.Size) {
ULONG SizeNeeded;
PUCHAR AllocatedMemory;
PPX_VC *NewTable;
//
// Grow the table
//
SizeNeeded =
(VcTable.Size + VcTable.Size/2) * sizeof(PPX_VC);
PxAllocMem(AllocatedMemory, SizeNeeded, PX_VCTABLE_TAG);
if (AllocatedMemory == NULL) {
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
return (FALSE);
}
RtlZeroMemory(AllocatedMemory,SizeNeeded);
NewTable = (PPX_VC*)AllocatedMemory;
RtlMoveMemory((PUCHAR)NewTable,
(PUCHAR)VcTable.Table,
(sizeof(PPX_VC) * VcTable.Size));
PxFreeMem(VcTable.Table);
VcTable.Table = NewTable;
VcTable.Size += VcTable.Size/2;
}
i = VcTable.Size;
index = VcTable.NextSlot;
do {
if (VcTable.Table[index] == NULL) {
NdisDprAcquireSpinLock(&pVc->Lock);
pVc->hdCall = index;
VcTable.Table[index] = pVc;
InsertTailList(&VcTable.List,
&pVc->Linkage);
VcTable.Count++;
VcTable.NextSlot =
(VcTable.NextSlot + 1) % VcTable.Size;
pVc->Flags |= PX_VC_IN_TABLE;
pClAf = pVc->ClAf;
NdisDprReleaseSpinLock(&pVc->Lock);
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Inserting pVc %x in VcTable hdCall %d\n", pVc, pVc->hdCall));
break;
}
index = (index+1) % VcTable.Size;
} while (--i);
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
if (i != 0) {
NdisAcquireSpinLock(&pClAf->Lock);
REF_CL_AF(pClAf);
InsertTailList(&pClAf->VcList, &pVc->ClAfLinkage);
NdisReleaseSpinLock(&pClAf->Lock);
} else {
PXDEBUGP(PXD_TAPI,PXM_TAPI, ("Failed to insert pVc %x in VcTable\n", pVc));
}
return (i != 0);
}
VOID
RemoveVcFromTable(
PPX_VC pVc
)
{
LOCK_STATE LockState;
PPX_CL_AF pClAf;
PXDEBUGP(PXD_TAPI, PXM_TAPI, ("Removing pVc %x from VcTable hdCall %d\n", pVc, pVc->hdCall));
NdisAcquireReadWriteLock(&VcTable.Lock, TRUE, &LockState);
ASSERT(VcTable.Table[pVc->hdCall] == pVc);
VcTable.Table[pVc->hdCall] = NULL;
VcTable.Count--;
NdisDprAcquireSpinLock(&pVc->Lock);
RemoveEntryList(&pVc->Linkage);
pVc->Flags &= ~PX_VC_IN_TABLE;
pClAf = pVc->ClAf;
NdisDprReleaseSpinLock(&pVc->Lock);
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
NdisAcquireSpinLock(&pClAf->Lock);
RemoveEntryList(&pVc->ClAfLinkage);
DEREF_CL_AF_LOCKED(pClAf);
}
BOOLEAN
IsTapiLineValid(
ULONG hdLine,
PPX_TAPI_LINE *TapiLine
)
{
PPX_TAPI_LINE RetLine;
LOCK_STATE LockState;
ULONG i;
*TapiLine = NULL;
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE RetLine;
RetLine = LineTable.Table[i];
if ((RetLine != NULL) &&
(RetLine->hdLine == hdLine)) {
*TapiLine = RetLine;
NdisDprAcquireSpinLock(&RetLine->Lock);
REF_TAPILINE(RetLine);
NdisDprReleaseSpinLock(&RetLine->Lock);
break;
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
return (*TapiLine != NULL);
}
BOOLEAN
IsTapiDeviceValid(
ULONG ulDeviceID,
PPX_TAPI_LINE *TapiLine
)
{
LOCK_STATE LockState;
ULONG i;
*TapiLine = NULL;
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
for (i = 0; i < LineTable.Size; i++) {
PPX_TAPI_LINE RetLine;
RetLine = LineTable.Table[i];
if ((RetLine != NULL) &&
(RetLine->ulDeviceID == ulDeviceID)) {
*TapiLine = RetLine;
NdisDprAcquireSpinLock(&RetLine->Lock);
REF_TAPILINE(RetLine);
NdisDprReleaseSpinLock(&RetLine->Lock);
break;
}
}
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
return (*TapiLine != NULL);
}
BOOLEAN
IsVcValid(
ULONG_PTR CallId,
PPX_VC *pVc
)
{
PPX_VC RetVc = NULL;
LOCK_STATE LockState;
ULONG i;
NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
if (CallId < VcTable.Size) {
RetVc = VcTable.Table[CallId];
}
if (RetVc != NULL) {
NdisDprAcquireSpinLock(&RetVc->Lock);
REF_VC(RetVc);
NdisDprReleaseSpinLock(&RetVc->Lock);
}
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
*pVc = RetVc;
return (RetVc != NULL);
}
VOID
GetVcFromCtx(
NDIS_HANDLE VcCtx,
PPX_VC *pVc
)
{
PPX_VC RetVc = NULL;
ULONG_PTR i;
LOCK_STATE LockState;
NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
i = (ULONG_PTR)(VcCtx);
if (i < VcTable.Size) {
RetVc = VcTable.Table[i];
}
if (RetVc != NULL) {
NdisDprAcquireSpinLock(&RetVc->Lock);
REF_VC(RetVc);
NdisDprReleaseSpinLock(&RetVc->Lock);
}
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
*pVc = RetVc;
}
//
// Function assumes that the TapiLine's spinlock is held!
//
BOOLEAN
IsAddressValid(
PPX_TAPI_LINE TapiLine,
ULONG AddressId,
PPX_TAPI_ADDR *TapiAddr
)
{
PPX_TAPI_ADDR RetAddr = NULL;
do {
if (AddressId >= TapiLine->AddrTable.Count) {
break;
}
RetAddr = TapiLine->AddrTable.Table[AddressId];
} while (FALSE);
*TapiAddr = RetAddr;
return (RetAddr != NULL);
}
BOOLEAN
GetLineFromCmLineID(
PPX_TAPI_PROVIDER TapiProvider,
ULONG CmLineID,
PPX_TAPI_LINE *TapiLine
)
{
PPX_TAPI_LINE RetLine;
NdisAcquireSpinLock(&TapiProvider->Lock);
RetLine = (PPX_TAPI_LINE)
TapiProvider->LineList.Flink;
while ((PVOID)RetLine != (PVOID)&TapiProvider->LineList) {
if ((RetLine->CmLineID == CmLineID) &&
(RetLine->DevStatus->ulNumOpens != 0)) {
break;
}
RetLine = (PPX_TAPI_LINE)
RetLine->Linkage.Flink;
}
if ((PVOID)RetLine == (PVOID)&TapiProvider->LineList) {
RetLine = NULL;
}
NdisReleaseSpinLock(&TapiProvider->Lock);
*TapiLine = RetLine;
return (RetLine != NULL);
}
BOOLEAN
GetAvailLineFromProvider(
PPX_TAPI_PROVIDER TapiProvider,
PPX_TAPI_LINE *TapiLine,
PPX_TAPI_ADDR *TapiAddr
)
{
LOCK_STATE LockState;
ULONG i;
PPX_TAPI_LINE tl;
NdisAcquireSpinLock(&TapiProvider->Lock);
tl = (PPX_TAPI_LINE)TapiProvider->LineList.Flink;
while ((PVOID)tl != (PVOID)&TapiProvider->LineList) {
PTAPI_ADDR_TABLE AddrTable;
PPX_TAPI_ADDR ta;
NdisDprAcquireSpinLock(&tl->Lock);
if (tl->DevStatus->ulNumOpens != 0) {
AddrTable = &tl->AddrTable;
ta = (PPX_TAPI_ADDR)AddrTable->List.Flink;
//
// Walk the addresses on this line
//
while ((PVOID)ta != (PVOID)&AddrTable->List) {
//
// If this address has a callcount that is
// < then the max num it supports, add another
// call on this address!
//
if (ta->CallCount < ta->Caps->ulMaxNumActiveCalls) {
*TapiLine = tl;
*TapiAddr = ta;
NdisDprReleaseSpinLock(&tl->Lock);
NdisReleaseSpinLock(&TapiProvider->Lock);
return (TRUE);
}
ta = (PPX_TAPI_ADDR)ta->Linkage.Flink;
}
}
NdisDprReleaseSpinLock(&tl->Lock);
tl = (PPX_TAPI_LINE)tl->Linkage.Flink;
}
NdisReleaseSpinLock(&TapiProvider->Lock);
return (FALSE);
}
//
// Function assumes that the TapiLine's spinlock is held!
//
PPX_TAPI_ADDR
GetAvailAddrFromLine(
PPX_TAPI_LINE TapiLine
)
{
PPX_TAPI_ADDR TapiAddr;
PTAPI_ADDR_TABLE AddrTable;
AddrTable = &TapiLine->AddrTable;
TapiAddr = (PPX_TAPI_ADDR)AddrTable->List.Flink;
//
// Walk the addresses on this line
//
while ((PVOID)TapiAddr != (PVOID)&AddrTable->List) {
//
// If this address has a callcount that is
// < then the max num it supports, add another
// call on this address!
//
if (TapiAddr->CallCount <
TapiAddr->Caps->ulMaxNumActiveCalls) {
return (TapiAddr);
}
TapiAddr = (PPX_TAPI_ADDR)TapiAddr->Linkage.Flink;
}
return (NULL);
}
BOOLEAN
InsertLineInTable(
PPX_TAPI_LINE TapiLine
)
{
ULONG i;
ULONG index;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PUCHAR AllocatedMemory;
LOCK_STATE LockState;
NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
if (LineTable.Count == LineTable.Size) {
ULONG SizeNeeded;
PUCHAR AllocatedMemory;
PPX_TAPI_LINE *NewTable;
//
// Grow the table
//
SizeNeeded =
(LineTable.Size + LineTable.Size/2) * sizeof(PPX_TAPI_LINE);
PxAllocMem(AllocatedMemory, SizeNeeded, PX_LINETABLE_TAG);
if (AllocatedMemory == NULL) {
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
return (FALSE);
}
RtlZeroMemory(AllocatedMemory,SizeNeeded);
NewTable = (PPX_TAPI_LINE*)AllocatedMemory;
RtlMoveMemory((PUCHAR)NewTable,
(PUCHAR)LineTable.Table,
(sizeof(PPX_TAPI_LINE) * LineTable.Size));
PxFreeMem(LineTable.Table);
LineTable.Table = NewTable;
LineTable.Size += LineTable.Size/2;
}
i = LineTable.Size;
index = LineTable.NextSlot;
do {
if (LineTable.Table[index] == NULL) {
TapiLine->hdLine = index;
TapiLine->Flags |= PX_LINE_IN_TABLE;
LineTable.Table[index] = TapiLine;
LineTable.Count++;
LineTable.NextSlot =
(LineTable.NextSlot + 1) % LineTable.Size;
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("Inserting TapiLine %p in LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
break;
}
index = (index+1) % LineTable.Size;
} while (--i);
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
#if DBG
if (i == 0) {
PXDEBUGP(PXD_TAPI,PXM_TAPI,
("Failed to insert TapiLine %p in LineTable\n", TapiLine));
}
#endif
return (i != 0);
}
VOID
RemoveTapiLineFromTable(
PPX_TAPI_LINE TapiLine
)
{
LOCK_STATE LockState;
PXDEBUGP(PXD_TAPI, PXM_TAPI,
("Removing TapiLine %p from LineTable hdCall %d\n", TapiLine, TapiLine->hdLine));
NdisAcquireReadWriteLock(&LineTable.Lock, TRUE, &LockState);
ASSERT(LineTable.Table[TapiLine->hdLine] == TapiLine);
LineTable.Table[TapiLine->hdLine] = NULL;
TapiLine->Flags &= ~PX_LINE_IN_TABLE;
LineTable.Count--;
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
}
NDIS_STATUS
PxVcCleanup(
PPX_VC pVc,
ULONG Flags
)
{
NDIS_STATUS Status;
PXDEBUGP(PXD_LOUD, PXM_TAPI,
("PxVcCleanup: Vc %p, State: %x, HandoffState: %x VcFlags: %x, NewFlags: %x\n",
pVc, pVc->State, pVc->HandoffState, Flags, pVc->Flags, Flags));
//
// Terminate Digit Gathering or Monitoring.
//
if (pVc->ulMonitorDigitsModes != 0) {
NdisReleaseSpinLock(&pVc->Lock);
PxStopDigitReporting(pVc);
NdisAcquireSpinLock(&pVc->Lock);
pVc->ulMonitorDigitsModes = 0;
} else if (pVc->PendingGatherDigits != NULL) {
PNDISTAPI_REQUEST pNdisTapiRequest = pVc->PendingGatherDigits;
pVc->PendingGatherDigits = NULL;
PxTerminateDigitDetection(pVc, pNdisTapiRequest, LINEGATHERTERM_CANCEL);
}
switch (pVc->State) {
case PX_VC_IDLE:
//
// Already idle do nothing.
//
Status = NDIS_STATUS_SUCCESS;
break;
case PX_VC_PROCEEDING:
//
// We have an outgoing call, when it completes close
// it down with ndis and complete the drop when
// in PxClCloseCallComplete.
//
pVc->PrevState = pVc->State;
pVc->State = PX_VC_DISCONNECTING;
//
// Attempt to close the call directly
// if this fails we will cleanup when
// the outgoing call completes
//
pVc->Flags |= (PX_VC_OUTCALL_ABORTING |
PX_VC_CLEANUP_CM |
Flags);
PxCloseCallWithCm(pVc);
Status = NDIS_STATUS_PENDING;
break;
case PX_VC_OFFERING:
//
// We have an incoming call offered to tapi. Close
// it down now by calling it's callcomplete handler
// with a non-success value.
//
pVc->Flags |= (Flags |
PX_VC_INCALL_ABORTING);
pVc->PrevState = pVc->State;
if (pVc->Flags & PX_VC_CLEANUP_CM) {
pVc->State= PX_VC_DISCONNECTING;
} else {
pVc->State = PX_VC_IDLE;
}
if (pVc->Flags & PX_VC_CALLTIMER_STARTED) {
PxStopIncomingCallTimeout(pVc);
}
NdisReleaseSpinLock(&pVc->Lock);
NdisClIncomingCallComplete(NDIS_STATUS_FAILURE,
pVc->ClVcHandle,
pVc->pCallParameters);
NdisAcquireSpinLock(&pVc->Lock);
if (pVc->Flags & PX_VC_CLEANUP_CM) {
PxCloseCallWithCm(pVc);
} else {
SendTapiCallState(pVc,
LINECALLSTATE_DISCONNECTED,
0,
pVc->CallInfo->ulMediaMode);
//
// Remove the ref applied in PxClIncomingCall.
// Don't use the full deref code here as the
// ref applied when we mapped the vc will
// keep the vc around.
//
pVc->RefCount--;
}
Status = NDIS_STATUS_SUCCESS;
break;
case PX_VC_DISCONNECTING:
pVc->Flags |= (Flags);
Status = NDIS_STATUS_PENDING;
break;
case PX_VC_CONNECTED:
//
// We have a call that needs to be closed with ndis.
// This may include dropping the call with a client
// depending on the handoff state. Complete the drop
// irp in PxClCloseCallComplete
//
if (!(pVc->Flags & PX_VC_DROP_PENDING)) {
pVc->PrevState = pVc->State;
pVc->State = PX_VC_DISCONNECTING;
pVc->Flags |= (Flags | PX_VC_CLEANUP_CM);
Status =
PxCloseCallWithCl(pVc);
if (Status != NDIS_STATUS_PENDING) {
PxCloseCallWithCm(pVc);
}
}
Status = NDIS_STATUS_PENDING;
break;
default:
PXDEBUGP(PXD_FATAL, PXM_TAPI,
("PxVcCleanup: Invalid VcState! Vc: %p VcState: %x CallState: %x\n",
pVc, pVc->State, pVc->ulCallState ));
Status = NDIS_STATUS_FAILURE;
ASSERT(0);
break;
}
return (Status);
}