2020-09-30 17:12:29 +02:00

594 lines
11 KiB
C

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
D:\nt\private\ntos\ndis\aic5900\vc.c
Abstract:
Author:
Kyle Brandon (KyleB)
Environment:
Kernel mode
Revision History:
--*/
#include "aic5900.h"
#define MODULE_NUMBER MODULE_VC
NDIS_STATUS
Aic5900CreateVc(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE NdisVcHandle,
OUT PNDIS_HANDLE MiniportVcContext
)
/*++
Routine Description:
This is the NDIS 4.1 handler to create a VC. This will allocate necessary
system resources for the VC.
Arguments:
MiniportAdapterContext - Pointer to our ADAPTER_BLOCK.
NdisVcHandle - Handle that NDIS uses to identify the VC that
is about to be created.
MiniportVcContext - Storage to hold context information about
the newly created VC.
Return Value:
NDIS_STATUS_SUCCESS if we successfully create the new VC.
--*/
{
PADAPTER_BLOCK pAdapter = (PADAPTER_BLOCK)MiniportAdapterContext;
PVC_BLOCK pVc;
NDIS_STATUS Status;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("==>Aic5900CreateVc\n"));
//
// I'm paranoid.
//
MiniportVcContext = NULL;
//
// Allocate memory for the VC.
//
ALLOCATE_MEMORY(&Status, &pVc, sizeof(VC_BLOCK));
if (NDIS_STATUS_SUCCESS != Status)
{
return(NDIS_STATUS_RESOURCES);
}
//
// Initialize memory.
//
NdisZeroMemory(pVc, sizeof(VC_BLOCK));
//
// Save a pointer to the adapter block with the vc.
//
pVc->Adapter = pAdapter;
pVc->NdisVcHandle = NdisVcHandle;
pVc->References = 1;
NdisAllocateSpinLock(&pVc->Lock);
NdisAcquireSpinLock(&pAdapter->Lock);
//
// Add the VC to the adapter's inactive list.
//
InsertHeadList(&pAdapter->InactiveVcList, &pVc->Link);
//
// This adapter has another reference...
//
pAdapter->References++;
NdisReleaseSpinLock(&pAdapter->Lock);
//
// Return the pointer to the new VC as the context.
//
MiniportVcContext = (PNDIS_HANDLE)pVc;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("<==Aic5900CreateVc\n"));
return(Status);
}
NDIS_STATUS
Aic5900DeleteVc(
IN NDIS_HANDLE MiniportVcContext
)
/*++
Routine Description:
This is the NDIS 4.1 handler to delete a given VC. This routine will
free any resources that are associated with the VC. For the VC to
be deleted it MUST be deactivated first.
Arguments:
MiniportVcContext - Pointer to the VC_BLOCK describing the VC that
is to be deleted.
Return Value:
NDIS_STATUS_SUCCESS if the VC is successfully deleted.
--*/
{
PVC_BLOCK pVc = (PVC_BLOCK)MiniportVcContext;
PADAPTER_BLOCK pAdapter = pVc->Adapter;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("==>Aic5900DeleteVc\n"));
NdisAcquireSpinLock(&pAdapter->Lock);
NdisDprAcquireSpinLock(&pVc->Lock);
//
// Verify that this VC is inactive.
//
if (VC_TEST_FLAG(pVc, (fVC_ACTIVE | fVC_DEACTIVATING)))
{
//
// Cannot delete a VC that is still active.
//
NdisDprReleaseSpinLock(&pVc->Lock);
NdisReleaseSpinLock(&pAdapter->Lock);
return(NDIS_STATUS_FAILURE);
}
//
// If a VC is deactive then it had better have only the creation
// reference count on it!
//
ASSERT(1 == pVc->References);
//
// Remove the VC from the inactive list.
//
RemoveEntryList(&pVc->Link);
NdisDprReleaseSpinLock(&pVc->Lock);
NdisReleaseSpinLock(&pAdapter->Lock);
//
// Clean up the resources that were allocated on behalf of the
// VC_BLOCK.
//
NdisFreeSpinLock(&pVc->Lock);
//
// Free the memory that was taken by the vc.
//
FREE_MEMORY(pVc, sizeof(PVC_BLOCK));
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("<==Aic5900DeleteVc\n"));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
aic5900AllocateTransmitSegment(
IN PADAPTER_BLOCK pAdapter,
IN PVC_BLOCK pVc,
IN PATM_MEDIA_PARAMETERS pMediaParms
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NDIS_STATUS Status;
//
// We do different things based upon the service category.
//
switch (pMediaParms->Transmit.ServiceCategory)
{
case ATM_SERVICE_CATEGORY_UBR:
break;
case ATM_SERVICE_CATEGORY_CBR:
break;
default:
Status = NDIS_STATUS_INVALID_DATA;
break;
}
return(Status);
}
NDIS_STATUS
aic5900ValidateVpiVci(
IN PADAPTER_BLOCK pAdapter,
IN PATM_MEDIA_PARAMETERS pMediaParms
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PVC_BLOCK pCurrentVc;
NDIS_STATUS Status;
BOOLEAN fInvalidVc = FALSE;
//
// We only support VPI of 0!
//
if (pMediaParms->ConnectionId.Vpi != 0)
{
return(NDIS_STATUS_FAILURE);
}
if ((pMediaParms->ConnectionId.Vci < MIN_VCS) ||
(pMediaParms->ConnectionId.Vci > (MAX_VCS - 1)))
{
return(NDIS_STATUS_FAILURE);
}
//
// See if we have a VC with the given VPI/VCI
//
pCurrentVc = CONTAINING_RECORD(&pAdapter->ActiveVcList.Flink, VC_BLOCK, Link);
while (pCurrentVc != (PVC_BLOCK)&pAdapter->ActiveVcList)
{
if ((pCurrentVc->VpiVci.Vpi == pMediaParms->ConnectionId.Vpi) &&
(pCurrentVc->VpiVci.Vci == pMediaParms->ConnectionId.Vci))
{
fInvalidVc = TRUE;
break;
}
pCurrentVc = (PVC_BLOCK)pCurrentVc->Link.Flink;
}
//
// Did we find a VC with the given VPI/VCI.
//
if (fInvalidVc)
{
return(NDIS_STATUS_FAILURE);
}
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
Aic5900ActivateVc(
IN NDIS_HANDLE MiniportVcContext,
IN PCO_MEDIA_PARAMETERS MediaParameters
)
/*++
Routine Description:
This is the NDIS 4.1 handler to activate a given VC. This will allocate
hardware resources, e.g. QoS, for a VC that was already created.
Arguments:
MiniportVcContext - Pointer to the VC_BLOCK representing the VC to
activate.
MediaParameters - ATM parameters (in our case) that are used to
describe the VC.
Return Value:
NDIS_STATUS_SUCCESS if the VC is successfully activated.
--*/
{
PVC_BLOCK pVc = (PVC_BLOCK)MiniportVcContext;
PADAPTER_BLOCK pAdapter = pVc->Adapter;
PATM_MEDIA_PARAMETERS pMediaParms;
PVC_BLOCK pTempVc;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("==>Aic5900ActivateVc"));
NdisDprAcquireSpinLock(&pVc->Lock);
do
{
//
// If the VC is already active then we will need to
// re-activate the VC with new parameters.....
//
if (VC_TEST_FLAG(pVc, fVC_ACTIVE))
{
//
// Not ready for this yet....
//
DbgBreakPoint();
}
//
// Are there any media specific parameters that we recognize?
//
if ((MediaParameters->MediaSpecific.ParamType != ATM_MEDIA_SPECIFIC) ||
(MediaParameters->MediaSpecific.Length != sizeof(ATM_MEDIA_PARAMETERS)))
{
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_ERR,
("Invalid media parameters for vc creation\n"));
Status = NDIS_STATUS_INVALID_DATA;
break;
}
pMediaParms = (PATM_MEDIA_PARAMETERS)MediaParameters->MediaSpecific.Parameters;
//
// Validate the VPI/VCI
//
Status = aic5900ValidateVpiVci(pAdapter, pMediaParms);
if (NDIS_STATUS_SUCCESS != Status)
{
break;
}
//
// Save the VCI with our VC information.
//
pVc->VpiVci = pMediaParms->ConnectionId;
//
// Check the AAL type.
//
if ((pMediaParms->AALType & (AAL_TYPE_AAL0 | AAL_TYPE_AAL5)) !=
(AAL_TYPE_AAL0 | AAL_TYPE_AAL5))
{
Status = NDIS_STATUS_INVALID_DATA;
break;
}
//
// Save the AAL information with our VC.
//
pVc->AALType = pMediaParms->AALType;
//
// Verify that we can support the given VC parameters.
//
if ((pVc->MediaFlags & TRANSMIT_VC) == TRANSMIT_VC)
{
VC_SET_FLAG(pVc, fVC_TRANSMIT);
//
// Allocate transmit resources.
//
Status = aic5900AllocateTransmitSegment(pAdapter, pVc, pMediaParms);
if (NDIS_STATUS_SUCCESS != Status)
{
}
}
if ((pVc->MediaFlags & RECEIVE_VC) == RECEIVE_VC)
{
VC_SET_FLAG(pVc, fVC_RECEIVE);
//
// Allocate receive resources.
//
}
VC_SET_FLAG(pVc, fVC_ACTIVE);
} while (FALSE);
NdisDprReleaseSpinLock(&pVc->Lock);
NdisReleaseSpinLock(&pAdapter->Lock);
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("<==Aic5900ActivateVc"));
return(Status);
}
NDIS_STATUS
Aic5900DeactivateVc(
IN NDIS_HANDLE MiniportVcContext
)
/*++
Routine Description:
This is the NDIS 4.1 handler to deactivate a given VC.
This does not free any resources, but simply marks the VC as unusable.
Arguments:
MiniportVcContext - Pointer to our VC_BLOCK that was allocated in
Aic5900CreateVc().
Return Value:
NDIS_STATUS_SUCCESS if we successfully deactivate the VC.
--*/
{
PVC_BLOCK pVc = (PVC_BLOCK)MiniportVcContext;
PADAPTER_BLOCK pAdapter = pVc->Adapter;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("==>Aic5900DeactivateVc\n"));
NdisAcquireSpinLock(&pAdapter->Lock);
if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RESET_IN_PROGRESS))
{
NdisReleaseSpinLock(&pAdapter->Lock);
return(NDIS_STATUS_RESET_IN_PROGRESS);
}
NdisDprAcquireSpinLock(&pVc->Lock);
do
{
if (!VC_TEST_FLAG(pVc, fVC_ACTIVE) ||
VC_TEST_FLAG(pVc, fVC_DEACTIVATING))
{
Status = NDIS_STATUS_FAILURE;
break;
}
//
// Mark the VC.
//
VC_CLEAR_FLAG(pVc, fVC_ACTIVE);
//
// Can't deactivate a VC with outstanding references....
//
if (pVc->References > 1)
{
Status = NDIS_STATUS_PENDING;
break;
}
aic5900DeactivateVcComplete(pAdapter, pVc);
} while (FALSE);
//
// If we are pending the deactivation then mark the VC as
// deactivating.
//
if (Status == NDIS_STATUS_PENDING)
{
VC_SET_FLAG(pVc, fVC_DEACTIVATING);
}
NdisDprReleaseSpinLock(&pVc->Lock);
NdisReleaseSpinLock(&pAdapter->Lock);
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("<==Aic5900DeactivateVc\n"));
return(NDIS_STATUS_SUCCESS);
}
VOID
aic5900DeactivateVcComplete(
IN PADAPTER_BLOCK pAdapter,
IN PVC_BLOCK pVc
)
/*++
Routine Description:
This routine is called to complete the deactivation of the VC.
this does NOT call NdisMCoDeactivateVcComplete() it is simply a place
to put common code...
Arguments:
pAdapter - Pointer to the ADAPTER_BLOCK owning the VC.
pVc - Pointer to the VC that is being deactivated.
Return Value:
Notes:
THIS ROUTINE MUST BE CALLED WITH BOTH THE ADAPTER_BLOCK AND THE VC'S
LOCKS ACQUIRED!!!!!
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("==>DeactivateVcComplete\n"));
ASSERT(!VC_TEST_FLAG(pVc, fVC_ACTIVE));
ASSERT(pVc->References == 1);
//
// Remove the VC from the active list and place it on the inactive list.
//
RemoveEntryList(&pVc->Link);
InsertHeadList(&pAdapter->InactiveVcList, &pVc->Link);
//
// Free up an transmit resources...
//
if (VC_TEST_FLAG(pVc, fVC_TRANSMIT))
{
}
//
// Free up any receive resources...
//
if (VC_TEST_FLAG(pVc, fVC_RECEIVE))
{
}
//
// If this is a pending call then complete the deactivation back to
// the call manager.
//
if (VC_TEST_FLAG(pVc, fVC_DEACTIVATING))
{
NdisDprReleaseSpinLock(&pVc->Lock);
NdisReleaseSpinLock(&pAdapter->Lock);
NdisMCoDeactivateVcComplete(Status, pVc->NdisVcHandle);
NdisAcquireSpinLock(&pAdapter->Lock);
NdisDprAcquireSpinLock(&pVc->Lock);
}
DBGPRINT(DBG_COMP_VC, DBG_LEVEL_INFO,
("<==DeactivateVcComplete\n"));
}