Source code of Windows XP (NT5)
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.

358 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. arbiter.c
  5. Abstract:
  6. This module provides arbiters for the resources consumed by PDOs.
  7. Author:
  8. Andy Thornton (andrewth) 20-Oct-97
  9. Revision History:
  10. --*/
  11. #include "mfp.h"
  12. #include "arbiter.h"
  13. NTSTATUS
  14. MfInitializeArbiters(
  15. IN PMF_PARENT_EXTENSION Parent
  16. );
  17. NTSTATUS
  18. MfInitializeArbiter(
  19. OUT PMF_ARBITER Arbiter,
  20. IN PDEVICE_OBJECT BusDeviceObject,
  21. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  22. );
  23. LONG
  24. MfNopScore(
  25. IN PIO_RESOURCE_DESCRIPTOR Descriptor
  26. );
  27. NTSTATUS
  28. MfStartArbiter(
  29. IN PARBITER_INSTANCE Arbiter,
  30. IN PCM_RESOURCE_LIST StartResources
  31. );
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text(PAGE, MfInitializeArbiters)
  34. #pragma alloc_text(PAGE, MfInitializeArbiter)
  35. #pragma alloc_text(PAGE, MfNopScore)
  36. #pragma alloc_text(PAGE, MfStartArbiter)
  37. #endif
  38. NTSTATUS
  39. MfInitializeArbiters(
  40. IN PMF_PARENT_EXTENSION Parent
  41. )
  42. /*++
  43. Routine Description:
  44. This initializes the arbiters required to arbitrated resources for the
  45. parent device.
  46. Arguments:
  47. Parent - The MF device we are initializing arbiters for.
  48. Return Value:
  49. Status of operation.
  50. --*/
  51. {
  52. NTSTATUS status;
  53. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
  54. PMF_ARBITER arbiter, newArbiter = NULL;
  55. BOOLEAN existingArbiter;
  56. PAGED_CODE();
  57. //
  58. // REBALANCE - if restart then free the old arbiters
  59. // until we do that, assume we're not restarting
  60. //
  61. ASSERT(IsListEmpty(&Parent->Arbiters));
  62. //
  63. // If we don't have any resources we don't need any arbiters
  64. //
  65. if (!Parent->ResourceList) {
  66. return STATUS_SUCCESS;
  67. }
  68. FOR_ALL_CM_DESCRIPTORS(Parent->ResourceList, descriptor) {
  69. //
  70. // Check if this is an nonarbitrated resource - if it is then we won't
  71. // be needing an arbiter for it!
  72. //
  73. if (!IS_ARBITRATED_RESOURCE(descriptor->Type)) {
  74. continue;
  75. }
  76. //
  77. // See if we already have an arbiter for this resource
  78. //
  79. existingArbiter = FALSE;
  80. FOR_ALL_IN_LIST(MF_ARBITER, &Parent->Arbiters, arbiter) {
  81. if (arbiter->Type == descriptor->Type) {
  82. //
  83. // We already have an arbiter so we don't need
  84. // to create a new one
  85. //
  86. existingArbiter = TRUE;
  87. break;
  88. }
  89. }
  90. if (!existingArbiter) {
  91. //
  92. // We don't have an arbiter for this resource type so make one!
  93. //
  94. DEBUG_MSG(1,
  95. ("Creating arbiter for %s\n",
  96. MfDbgCmResourceTypeToText(descriptor->Type)
  97. ));
  98. newArbiter = ExAllocatePoolWithTag(PagedPool,
  99. sizeof(MF_ARBITER),
  100. MF_ARBITER_TAG
  101. );
  102. if (!newArbiter) {
  103. return STATUS_INSUFFICIENT_RESOURCES;
  104. }
  105. status = MfInitializeArbiter(newArbiter, Parent->Self, descriptor);
  106. if (!NT_SUCCESS(status)) {
  107. goto cleanup;
  108. }
  109. InsertHeadList(&Parent->Arbiters, &newArbiter->ListEntry);
  110. }
  111. }
  112. FOR_ALL_IN_LIST(MF_ARBITER, &Parent->Arbiters, arbiter) {
  113. MfStartArbiter(&(arbiter->Instance), Parent->ResourceList);
  114. }
  115. return STATUS_SUCCESS;
  116. cleanup:
  117. if (newArbiter) {
  118. ExFreePool(newArbiter);
  119. }
  120. return status;
  121. }
  122. LONG
  123. MfNopScore(
  124. IN PIO_RESOURCE_DESCRIPTOR Descriptor
  125. )
  126. {
  127. PAGED_CODE();
  128. return 0;
  129. }
  130. NTSTATUS
  131. MfInitializeArbiter(
  132. OUT PMF_ARBITER Arbiter,
  133. IN PDEVICE_OBJECT BusDeviceObject,
  134. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  135. )
  136. /*
  137. Routine Description:
  138. This initializes an arbiter to arbitrated the resources described in
  139. Descriptor
  140. Arguments:
  141. Arbiter - Pointer to a buffer where the arbiter should reside.
  142. Descriptor - Describes the resources available to the arbiter.
  143. Return Value:
  144. Status of operation.
  145. */
  146. {
  147. NTSTATUS status;
  148. PMF_RESOURCE_TYPE resType;
  149. PAGED_CODE();
  150. //
  151. // Do we understand these resources
  152. //
  153. resType = MfFindResourceType(Descriptor->Type);
  154. if (!resType) {
  155. return STATUS_INVALID_PARAMETER;
  156. }
  157. Arbiter->Type = Descriptor->Type;
  158. RtlZeroMemory(&Arbiter->Instance, sizeof(ARBITER_INSTANCE));
  159. Arbiter->Instance.PackResource = resType->PackResource;
  160. Arbiter->Instance.UnpackResource = resType->UnpackResource;
  161. Arbiter->Instance.UnpackRequirement = resType->UnpackRequirement;
  162. //
  163. // Initialize the arbiter
  164. //
  165. status = ArbInitializeArbiterInstance(&Arbiter->Instance,
  166. BusDeviceObject,
  167. Arbiter->Type,
  168. L"Mf Arbiter",
  169. L"Root", // should be NULL
  170. NULL
  171. );
  172. return status;
  173. }
  174. //
  175. // Arbiter support functions
  176. //
  177. NTSTATUS
  178. MfStartArbiter(
  179. IN PARBITER_INSTANCE Arbiter,
  180. IN PCM_RESOURCE_LIST StartResources
  181. )
  182. /*++
  183. Routine Description:
  184. This initializes an arbiter's range list to arbitrate the
  185. resources described in StartResources
  186. Arguments:
  187. Arbiter - Pointer to the arbiter.
  188. StartResources - Describes the resources available to the arbiter.
  189. Return Value:
  190. Status of operation.
  191. --*/
  192. {
  193. RTL_RANGE_LIST invertedAllocation;
  194. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
  195. ULONGLONG start;
  196. ULONG length;
  197. NTSTATUS status;
  198. PAGED_CODE();
  199. RtlInitializeRangeList(&invertedAllocation);
  200. //
  201. // Iterate through resource descriptors, adding the resources
  202. // this arbiter arbitrates to the ReverseAllocation
  203. //
  204. FOR_ALL_CM_DESCRIPTORS(StartResources,descriptor) {
  205. if (descriptor->Type == Arbiter->ResourceType) {
  206. status = Arbiter->UnpackResource(descriptor,
  207. &start,
  208. &length);
  209. if (!NT_SUCCESS(status)) {
  210. goto cleanup;
  211. }
  212. if (length > 0) {
  213. //
  214. // we don't care about Attributes, UserData or Owner since this
  215. // list is going to get trashed in a minute anyway
  216. //
  217. status = RtlAddRange(&invertedAllocation,
  218. start,
  219. END_OF_RANGE(start,length),
  220. 0, // Attributes
  221. RTL_RANGE_LIST_ADD_SHARED|RTL_RANGE_LIST_ADD_IF_CONFLICT,
  222. 0, // UserData
  223. NULL); // Owner
  224. }
  225. if (!NT_SUCCESS(status)) {
  226. goto cleanup;
  227. }
  228. }
  229. }
  230. status = RtlInvertRangeList(Arbiter->Allocation,&invertedAllocation);
  231. if (!NT_SUCCESS(status)) {
  232. goto cleanup;
  233. }
  234. status = STATUS_SUCCESS;
  235. cleanup:
  236. RtlFreeRangeList(&invertedAllocation);
  237. return status;
  238. }