594 lines
11 KiB
C
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"));
|
|
}
|