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

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. extlist.c
  5. Abstract:
  6. This module contains routines for managing ACPI extension lists
  7. Author:
  8. Adrian J. Oney (AdriaO)
  9. Environment:
  10. NT Kernel Model Driver only
  11. These routines are meant to be used as a for loop, ie:
  12. Iterate over the list using:
  13. ACPIExtListSetupEnum(...);
  14. for(
  15. ACPIExtListStartEnum(...);
  16. ACPIExtListTestElement(...);
  17. ACPIExtListEnumNext(...)
  18. ) {
  19. if (GoingToBreak) {
  20. ACPIExtListExitEnumEarly(...);
  21. break ;
  22. }
  23. }
  24. Revision History:
  25. Feb 11, 1998 - Authored
  26. --*/
  27. #include "pch.h"
  28. BOOLEAN
  29. ACPIExtListIsFinished(
  30. IN PEXTENSIONLIST_ENUMDATA PExtList_EnumData
  31. )
  32. /*++
  33. Routine Description:
  34. Arguments:
  35. Return Value:
  36. --*/
  37. {
  38. ACPIDebugEnter( "ACPIExtListIsFinished" );
  39. if (CONTAINING_LIST(PExtList_EnumData->pDevExtCurrent,
  40. PExtList_EnumData->ExtOffset) == PExtList_EnumData->pListHead) {
  41. return TRUE ;
  42. }
  43. return FALSE ;
  44. ACPIDebugExit( "ACPIExtListIsFinished" );
  45. }
  46. PDEVICE_EXTENSION
  47. EXPORT
  48. ACPIExtListStartEnum(
  49. IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData
  50. )
  51. /*++
  52. Routine Description:
  53. Arguments:
  54. Return Value:
  55. --*/
  56. {
  57. ACPIDebugEnter( "ACPIExtListStartEnum" );
  58. //
  59. // We must walk the tree at dispatch level <sigh>
  60. //
  61. if (PExtList_EnumData->WalkScheme != WALKSCHEME_NO_PROTECTION) {
  62. KeAcquireSpinLock(
  63. PExtList_EnumData->pSpinLock,
  64. &PExtList_EnumData->oldIrql
  65. );
  66. }
  67. //
  68. // Grab the first element
  69. //
  70. PExtList_EnumData->pDevExtCurrent = CONTAINING_EXTENSION(
  71. PExtList_EnumData->pListHead->Flink,
  72. PExtList_EnumData->ExtOffset
  73. );
  74. //
  75. // Return null if the list is empty (leave the internal pointer alone
  76. // though...
  77. //
  78. if (ACPIExtListIsFinished(PExtList_EnumData)) {
  79. return NULL ;
  80. }
  81. return PExtList_EnumData->pDevExtCurrent ;
  82. ACPIDebugExit( "ACPIExtListStartEnum" );
  83. }
  84. BOOLEAN
  85. EXPORT
  86. ACPIExtListTestElement(
  87. IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData,
  88. IN BOOLEAN ContinueEnumeration
  89. )
  90. /*++
  91. Routine Description:
  92. Arguments:
  93. Return Value:
  94. --*/
  95. {
  96. ACPIDebugEnter( "ACPIExtListTestElement" );
  97. //
  98. // If finished or stopping, simply release the spinlock
  99. //
  100. if (ACPIExtListIsFinished(PExtList_EnumData)||(!ContinueEnumeration)) {
  101. if (PExtList_EnumData->WalkScheme != WALKSCHEME_NO_PROTECTION) {
  102. KeReleaseSpinLock(
  103. PExtList_EnumData->pSpinLock,
  104. PExtList_EnumData->oldIrql
  105. );
  106. }
  107. return FALSE ;
  108. }
  109. if (PExtList_EnumData->WalkScheme == WALKSCHEME_REFERENCE_ENTRIES) {
  110. //
  111. // Always update the reference count to make sure that no one will
  112. // ever delete the node while our spinlock is down
  113. //
  114. InterlockedIncrement(
  115. &(PExtList_EnumData->pDevExtCurrent->ReferenceCount)
  116. );
  117. //
  118. // Relinquish the spin lock
  119. //
  120. KeReleaseSpinLock(
  121. PExtList_EnumData->pSpinLock,
  122. PExtList_EnumData->oldIrql
  123. );
  124. }
  125. return TRUE ;
  126. ACPIDebugExit( "ACPIExtListTestElement" );
  127. }
  128. PDEVICE_EXTENSION
  129. EXPORT
  130. ACPIExtListEnumNext(
  131. IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData
  132. )
  133. /*++
  134. Routine Description:
  135. Arguments:
  136. Return Value:
  137. --*/
  138. {
  139. LONG oldReferenceCount ;
  140. PDEVICE_EXTENSION nextExtension ;
  141. BOOLEAN enumComplete ;
  142. PLIST_ENTRY listEntry ;
  143. ACPIDebugEnter( "ACPIExtListEnumNext" );
  144. if (PExtList_EnumData->WalkScheme != WALKSCHEME_REFERENCE_ENTRIES) {
  145. PExtList_EnumData->pDevExtCurrent = CONTAINING_EXTENSION(
  146. CONTAINING_LIST(PExtList_EnumData->pDevExtCurrent,
  147. PExtList_EnumData->ExtOffset)->Flink,
  148. PExtList_EnumData->ExtOffset
  149. );
  150. enumComplete = ACPIExtListIsFinished(PExtList_EnumData) ;
  151. return enumComplete ? NULL : PExtList_EnumData->pDevExtCurrent ;
  152. }
  153. //
  154. // Reacquire the spin lock
  155. //
  156. KeAcquireSpinLock(
  157. PExtList_EnumData->pSpinLock,
  158. &PExtList_EnumData->oldIrql
  159. );
  160. //
  161. // Decrement the reference count on the node
  162. //
  163. oldReferenceCount = InterlockedDecrement(
  164. &(PExtList_EnumData->pDevExtCurrent->ReferenceCount)
  165. );
  166. ASSERT(!ACPIExtListIsFinished(PExtList_EnumData)) ;
  167. //
  168. // Next element
  169. //
  170. nextExtension = CONTAINING_EXTENSION(
  171. CONTAINING_LIST(PExtList_EnumData->pDevExtCurrent,
  172. PExtList_EnumData->ExtOffset)->Flink,
  173. PExtList_EnumData->ExtOffset
  174. );
  175. //
  176. // Remove the node, if necessary
  177. //
  178. if (oldReferenceCount == 0) {
  179. //
  180. // Deleted the old extension
  181. //
  182. ACPIInitDeleteDeviceExtension( PExtList_EnumData->pDevExtCurrent );
  183. }
  184. PExtList_EnumData->pDevExtCurrent = nextExtension ;
  185. enumComplete = ACPIExtListIsFinished(PExtList_EnumData) ;
  186. return enumComplete ? NULL : PExtList_EnumData->pDevExtCurrent ;
  187. ACPIDebugExit( "ACPIExtListEnumNext" );
  188. }
  189. VOID
  190. EXPORT
  191. ACPIExtListExitEnumEarly(
  192. IN OUT PEXTENSIONLIST_ENUMDATA PExtList_EnumData
  193. )
  194. /*++
  195. Routine Description:
  196. Arguments:
  197. Return Value:
  198. --*/
  199. {
  200. ACPIDebugEnter( "ACPIExtListExitEnumEarly" );
  201. //
  202. // Relinquish the spin lock
  203. //
  204. if (PExtList_EnumData->WalkScheme == WALKSCHEME_HOLD_SPINLOCK) {
  205. KeReleaseSpinLock(
  206. PExtList_EnumData->pSpinLock,
  207. PExtList_EnumData->oldIrql
  208. );
  209. }
  210. return ;
  211. ACPIDebugExit( "ACPIExtListExitEnumEarly" );
  212. }
  213. BOOLEAN
  214. EXPORT
  215. ACPIExtListIsMemberOfRelation(
  216. IN PDEVICE_OBJECT DeviceObject,
  217. IN PDEVICE_RELATIONS DeviceRelations
  218. )
  219. /*++
  220. Routine Description:
  221. This routine takes a given device object and a set of relations and
  222. checks to see if the object is already in the relation list.
  223. Arguments:
  224. DeviceObject - Device object to look for
  225. DeviceRelations - Relations we should examine
  226. Return Value:
  227. BOOLEAN - TRUE if DeviceObject is a member of the relation.
  228. --*/
  229. {
  230. ULONG index = 0;
  231. ACPIDebugEnter( "ACPIExtListIsMemberOfRelation" );
  232. //
  233. // If the list is empty, the answer is obvious...
  234. //
  235. if (DeviceRelations == NULL) return FALSE ;
  236. for (index = 0; index < DeviceRelations->Count; index++) {
  237. if (DeviceRelations->Objects[index] == DeviceObject) {
  238. return TRUE ;
  239. }
  240. }
  241. return FALSE ;
  242. ACPIDebugExit( "ACPIExtListIsMemberOfRelation" );
  243. }