Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

350 lines
6.9 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
extlist.c
Abstract:
This module contains routines for managing ACPI extension lists
Author:
Adrian J. Oney (AdriaO)
Environment:
NT Kernel Model Driver only
These routines are meant to be used as a for loop, ie:
Iterate over the list using:
ACPIExtListSetupEnum(...);
for(
ACPIExtListStartEnum(...);
ACPIExtListTestElement(...);
ACPIExtListEnumNext(...)
) {
if (GoingToBreak) {
ACPIExtListExitEnumEarly(...);
break ;
}
}
Revision History:
Feb 11, 1998 - Authored
--*/
#include "pch.h"
BOOLEAN
ACPIExtListIsFinished(
IN PEXTENSIONLIST_ENUMDATA PExtList_EnumData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
ACPIDebugEnter( "ACPIExtListIsFinished" );
if (CONTAINING_LIST(PExtList_EnumData->pDevExtCurrent,
PExtList_EnumData->ExtOffset) == PExtList_EnumData->pListHead) {
return TRUE ;
}
return FALSE ;
ACPIDebugExit( "ACPIExtListIsFinished" );
}
PDEVICE_EXTENSION
EXPORT
ACPIExtListStartEnum(
IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
ACPIDebugEnter( "ACPIExtListStartEnum" );
//
// We must walk the tree at dispatch level <sigh>
//
if (PExtList_EnumData->WalkScheme != WALKSCHEME_NO_PROTECTION) {
KeAcquireSpinLock(
PExtList_EnumData->pSpinLock,
&PExtList_EnumData->oldIrql
);
}
//
// Grab the first element
//
PExtList_EnumData->pDevExtCurrent = CONTAINING_EXTENSION(
PExtList_EnumData->pListHead->Flink,
PExtList_EnumData->ExtOffset
);
//
// Return null if the list is empty (leave the internal pointer alone
// though...
//
if (ACPIExtListIsFinished(PExtList_EnumData)) {
return NULL ;
}
return PExtList_EnumData->pDevExtCurrent ;
ACPIDebugExit( "ACPIExtListStartEnum" );
}
BOOLEAN
EXPORT
ACPIExtListTestElement(
IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData,
IN BOOLEAN ContinueEnumeration
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
ACPIDebugEnter( "ACPIExtListTestElement" );
//
// If finished or stopping, simply release the spinlock
//
if (ACPIExtListIsFinished(PExtList_EnumData)||(!ContinueEnumeration)) {
if (PExtList_EnumData->WalkScheme != WALKSCHEME_NO_PROTECTION) {
KeReleaseSpinLock(
PExtList_EnumData->pSpinLock,
PExtList_EnumData->oldIrql
);
}
return FALSE ;
}
if (PExtList_EnumData->WalkScheme == WALKSCHEME_REFERENCE_ENTRIES) {
//
// Always update the reference count to make sure that no one will
// ever delete the node while our spinlock is down
//
InterlockedIncrement(
&(PExtList_EnumData->pDevExtCurrent->ReferenceCount)
);
//
// Relinquish the spin lock
//
KeReleaseSpinLock(
PExtList_EnumData->pSpinLock,
PExtList_EnumData->oldIrql
);
}
return TRUE ;
ACPIDebugExit( "ACPIExtListTestElement" );
}
PDEVICE_EXTENSION
EXPORT
ACPIExtListEnumNext(
IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
LONG oldReferenceCount ;
PDEVICE_EXTENSION nextExtension ;
BOOLEAN enumComplete ;
PLIST_ENTRY listEntry ;
ACPIDebugEnter( "ACPIExtListEnumNext" );
if (PExtList_EnumData->WalkScheme != WALKSCHEME_REFERENCE_ENTRIES) {
PExtList_EnumData->pDevExtCurrent = CONTAINING_EXTENSION(
CONTAINING_LIST(PExtList_EnumData->pDevExtCurrent,
PExtList_EnumData->ExtOffset)->Flink,
PExtList_EnumData->ExtOffset
);
enumComplete = ACPIExtListIsFinished(PExtList_EnumData) ;
return enumComplete ? NULL : PExtList_EnumData->pDevExtCurrent ;
}
//
// Reacquire the spin lock
//
KeAcquireSpinLock(
PExtList_EnumData->pSpinLock,
&PExtList_EnumData->oldIrql
);
//
// Decrement the reference count on the node
//
oldReferenceCount = InterlockedDecrement(
&(PExtList_EnumData->pDevExtCurrent->ReferenceCount)
);
ASSERT(!ACPIExtListIsFinished(PExtList_EnumData)) ;
//
// Next element
//
nextExtension = CONTAINING_EXTENSION(
CONTAINING_LIST(PExtList_EnumData->pDevExtCurrent,
PExtList_EnumData->ExtOffset)->Flink,
PExtList_EnumData->ExtOffset
);
//
// Remove the node, if necessary
//
if (oldReferenceCount == 0) {
//
// Deleted the old extension
//
ACPIInitDeleteDeviceExtension( PExtList_EnumData->pDevExtCurrent );
}
PExtList_EnumData->pDevExtCurrent = nextExtension ;
enumComplete = ACPIExtListIsFinished(PExtList_EnumData) ;
return enumComplete ? NULL : PExtList_EnumData->pDevExtCurrent ;
ACPIDebugExit( "ACPIExtListEnumNext" );
}
VOID
EXPORT
ACPIExtListExitEnumEarly(
IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
ACPIDebugEnter( "ACPIExtListExitEnumEarly" );
//
// Relinquish the spin lock
//
if (PExtList_EnumData->WalkScheme == WALKSCHEME_HOLD_SPINLOCK) {
KeReleaseSpinLock(
PExtList_EnumData->pSpinLock,
PExtList_EnumData->oldIrql
);
}
return ;
ACPIDebugExit( "ACPIExtListExitEnumEarly" );
}
BOOLEAN
EXPORT
ACPIExtListIsMemberOfRelation(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_RELATIONS DeviceRelations
)
/*++
Routine Description:
This routine takes a given device object and a set of relations and
checks to see if the object is already in the relation list.
Arguments:
DeviceObject - Device object to look for
DeviceRelations - Relations we should examine
Return Value:
BOOLEAN - TRUE if DeviceObject is a member of the relation.
--*/
{
ULONG index = 0;
ACPIDebugEnter( "ACPIExtListIsMemberOfRelation" );
//
// If the list is empty, the answer is obvious...
//
if (DeviceRelations == NULL) return FALSE ;
for (index = 0; index < DeviceRelations->Count; index++) {
if (DeviceRelations->Objects[index] == DeviceObject) {
return TRUE ;
}
}
return FALSE ;
ACPIDebugExit( "ACPIExtListIsMemberOfRelation" );
}