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.

515 lines
11 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. NTSTATUS
  13. MfUnpackRequirement(
  14. IN PIO_RESOURCE_DESCRIPTOR Descriptor,
  15. OUT PULONGLONG Minimum,
  16. OUT PULONGLONG Maximum,
  17. OUT PULONG Length,
  18. OUT PULONG Alignment
  19. );
  20. NTSTATUS
  21. MfPackResource(
  22. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  23. IN ULONGLONG Start,
  24. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  25. );
  26. NTSTATUS
  27. MfUnpackResource(
  28. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  29. OUT PULONGLONG Start,
  30. OUT PULONG Length
  31. );
  32. NTSTATUS
  33. MfRequirementFromResource(
  34. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
  35. OUT PIO_RESOURCE_DESCRIPTOR Requirement
  36. );
  37. NTSTATUS
  38. MfUpdateResource(
  39. IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
  40. IN ULONGLONG Start,
  41. IN ULONG Length
  42. );
  43. //
  44. // Make everything pageable
  45. //
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text(PAGE, MfFindResourceType)
  48. #pragma alloc_text(PAGE, MfUnpackRequirement)
  49. #pragma alloc_text(PAGE, MfPackResource)
  50. #pragma alloc_text(PAGE, MfUnpackResource)
  51. #pragma alloc_text(PAGE, MfUpdateResource)
  52. #endif // ALLOC_PRAGMA
  53. //
  54. // This table describes the resource types that are understood by the MF driver.
  55. // It is implemented thus to that in the future MF could be educated about new
  56. // resource types dynamically.
  57. //
  58. MF_RESOURCE_TYPE MfResourceTypes[] = {
  59. {
  60. CmResourceTypePort,
  61. MfUnpackRequirement,
  62. MfPackResource,
  63. MfUnpackResource,
  64. MfRequirementFromResource,
  65. MfUpdateResource
  66. },
  67. {
  68. CmResourceTypeInterrupt,
  69. MfUnpackRequirement,
  70. MfPackResource,
  71. MfUnpackResource,
  72. MfRequirementFromResource,
  73. MfUpdateResource
  74. },
  75. {
  76. CmResourceTypeMemory,
  77. MfUnpackRequirement,
  78. MfPackResource,
  79. MfUnpackResource,
  80. MfRequirementFromResource,
  81. MfUpdateResource
  82. },
  83. {
  84. CmResourceTypeDma,
  85. MfUnpackRequirement,
  86. MfPackResource,
  87. MfUnpackResource,
  88. MfRequirementFromResource,
  89. MfUpdateResource
  90. },
  91. {
  92. CmResourceTypeBusNumber,
  93. MfUnpackRequirement,
  94. MfPackResource,
  95. MfUnpackResource,
  96. MfRequirementFromResource,
  97. MfUpdateResource
  98. }
  99. };
  100. NTSTATUS
  101. MfRequirementFromResource(
  102. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
  103. OUT PIO_RESOURCE_DESCRIPTOR Requirement
  104. )
  105. /*++
  106. Routine Description:
  107. This function build an requirements descriptor for a resource the parent is
  108. started with.
  109. Arguments:
  110. Resource - Pointer to the resource to make a requirement from
  111. Requirement - Pointer to a descriptor that should be filled in
  112. Return Value:
  113. Success or otherwise of the operation
  114. --*/
  115. {
  116. //
  117. // Copy the common fields
  118. //
  119. Requirement->Type = Resource->Type;
  120. Requirement->ShareDisposition = Resource->ShareDisposition;
  121. Requirement->Flags = Resource->Flags;
  122. //
  123. // Fill in the requirement
  124. //
  125. switch (Resource->Type) {
  126. case CmResourceTypeMemory:
  127. case CmResourceTypePort:
  128. //
  129. // We *DO NOT* support zero length requirements
  130. //
  131. if (Resource->u.Generic.Length == 0) {
  132. return STATUS_INVALID_PARAMETER;
  133. }
  134. Requirement->u.Generic.MinimumAddress = Resource->u.Generic.Start;
  135. Requirement->u.Generic.MaximumAddress.QuadPart =
  136. Resource->u.Generic.Start.QuadPart + Resource->u.Generic.Length - 1;
  137. Requirement->u.Generic.Length = Resource->u.Generic.Length;
  138. Requirement->u.Generic.Alignment = 1;
  139. break;
  140. case CmResourceTypeInterrupt:
  141. Requirement->u.Interrupt.MinimumVector = Resource->u.Interrupt.Vector;
  142. Requirement->u.Interrupt.MaximumVector = Resource->u.Interrupt.Vector;
  143. break;
  144. case CmResourceTypeDma:
  145. Requirement->u.Dma.MinimumChannel = Resource->u.Dma.Channel;
  146. Requirement->u.Dma.MinimumChannel = Resource->u.Dma.Channel;
  147. break;
  148. case CmResourceTypeBusNumber:
  149. //
  150. // We *DO NOT* support zero length requirements
  151. //
  152. if (Resource->u.BusNumber.Length == 0) {
  153. return STATUS_INVALID_PARAMETER;
  154. }
  155. Requirement->u.BusNumber.Length = Resource->u.BusNumber.Length;
  156. Requirement->u.BusNumber.MinBusNumber = Resource->u.BusNumber.Start;
  157. Requirement->u.BusNumber.MaxBusNumber = Resource->u.BusNumber.Start +
  158. Resource->u.BusNumber.Length - 1;
  159. break;
  160. case CmResourceTypeDevicePrivate:
  161. Requirement->u.DevicePrivate.Data[0] = Resource->u.DevicePrivate.Data[0];
  162. Requirement->u.DevicePrivate.Data[1] = Resource->u.DevicePrivate.Data[1];
  163. Requirement->u.DevicePrivate.Data[2] = Resource->u.DevicePrivate.Data[2];
  164. break;
  165. default:
  166. return STATUS_INVALID_PARAMETER;
  167. }
  168. return STATUS_SUCCESS;
  169. }
  170. PMF_RESOURCE_TYPE
  171. MfFindResourceType(
  172. IN CM_RESOURCE_TYPE Type
  173. )
  174. /*++
  175. Routine Description:
  176. This routine searches the database of know resource types to find the
  177. resource descriptor manipulation routines for resources of type Type.
  178. Arguments:
  179. Type - The resource type we are interested in.
  180. Return Value:
  181. Returns a pointer to the appropriate MF_RESOURCE_TYPE or NULL if one could
  182. not be found.
  183. --*/
  184. {
  185. PMF_RESOURCE_TYPE current;
  186. PAGED_CODE();
  187. FOR_ALL_IN_ARRAY(MfResourceTypes,
  188. sizeof(MfResourceTypes) / sizeof(MF_RESOURCE_TYPE),
  189. current
  190. ) {
  191. if (current->Type == Type) {
  192. return current;
  193. }
  194. }
  195. return NULL;
  196. }
  197. NTSTATUS
  198. MfUnpackRequirement(
  199. IN PIO_RESOURCE_DESCRIPTOR Descriptor,
  200. OUT PULONGLONG Minimum,
  201. OUT PULONGLONG Maximum,
  202. OUT PULONG Length,
  203. OUT PULONG Alignment
  204. )
  205. /*++
  206. Routine Description:
  207. This routine unpacks an resource requirement descriptor.
  208. Arguments:
  209. Descriptor - The descriptor describing the requirement to unpack.
  210. Minimum - Pointer to where the minimum acceptable start value should be
  211. unpacked to.
  212. Maximum - Pointer to where the maximum acceptable end value should be
  213. unpacked to.
  214. Length - Pointer to where the required length should be unpacked to.
  215. Minimum - Pointer to where the required alignment should be unpacked to.
  216. Return Value:
  217. Returns the status of this operation.
  218. --*/
  219. {
  220. PAGED_CODE();
  221. switch (Descriptor->Type) {
  222. case CmResourceTypePort:
  223. case CmResourceTypeMemory:
  224. *Maximum = Descriptor->u.Generic.MaximumAddress.QuadPart;
  225. *Minimum = Descriptor->u.Generic.MinimumAddress.QuadPart;
  226. *Length = Descriptor->u.Generic.Length;
  227. *Alignment = Descriptor->u.Generic.Alignment;
  228. break;
  229. case CmResourceTypeInterrupt:
  230. *Maximum = Descriptor->u.Interrupt.MaximumVector;
  231. *Minimum = Descriptor->u.Interrupt.MinimumVector;
  232. *Length = 1;
  233. *Alignment = 1;
  234. break;
  235. case CmResourceTypeDma:
  236. *Maximum = Descriptor->u.Dma.MaximumChannel;
  237. *Minimum = Descriptor->u.Dma.MinimumChannel;
  238. *Length = 1;
  239. *Alignment = 1;
  240. break;
  241. case CmResourceTypeBusNumber:
  242. *Maximum = Descriptor->u.BusNumber.MaxBusNumber;
  243. *Minimum = Descriptor->u.BusNumber.MinBusNumber;
  244. *Length = Descriptor->u.BusNumber.Length;
  245. *Alignment = 1;
  246. break;
  247. default:
  248. return STATUS_INVALID_PARAMETER;
  249. }
  250. return STATUS_SUCCESS;
  251. }
  252. NTSTATUS
  253. MfPackResource(
  254. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  255. IN ULONGLONG Start,
  256. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  257. )
  258. /*++
  259. Routine Description:
  260. This routine packs an resource descriptor.
  261. Arguments:
  262. Requirement - The requirement from which this resource was chosen.
  263. Start - The start value of the resource.
  264. Descriptor - Pointer to the descriptor to pack into.
  265. Return Value:
  266. Returns the status of this operation.
  267. --*/
  268. {
  269. PAGED_CODE();
  270. switch (Requirement->Type) {
  271. case CmResourceTypePort:
  272. case CmResourceTypeMemory:
  273. Descriptor->u.Generic.Start.QuadPart = Start;
  274. Descriptor->u.Generic.Length = Requirement->u.Generic.Length;
  275. break;
  276. case CmResourceTypeInterrupt:
  277. ASSERT(Start <= MAXULONG);
  278. Descriptor->u.Interrupt.Level = (ULONG)Start;
  279. Descriptor->u.Interrupt.Vector = (ULONG)Start;
  280. Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
  281. break;
  282. case CmResourceTypeDma:
  283. ASSERT(Start <= MAXULONG);
  284. Descriptor->u.Dma.Channel = (ULONG)Start;
  285. Descriptor->u.Dma.Port = 0;
  286. break;
  287. case CmResourceTypeBusNumber:
  288. ASSERT(Start <= MAXULONG);
  289. Descriptor->u.BusNumber.Start = (ULONG)Start;
  290. Descriptor->u.BusNumber.Length = Requirement->u.BusNumber.Length;
  291. break;
  292. default:
  293. return STATUS_INVALID_PARAMETER;
  294. }
  295. Descriptor->ShareDisposition = Requirement->ShareDisposition;
  296. Descriptor->Flags = Requirement->Flags;
  297. Descriptor->Type = Requirement->Type;
  298. return STATUS_SUCCESS;
  299. }
  300. NTSTATUS
  301. MfUnpackResource(
  302. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  303. OUT PULONGLONG Start,
  304. OUT PULONG Length
  305. )
  306. /*++
  307. Routine Description:
  308. This routine unpacks a resource descriptor.
  309. Arguments:
  310. Descriptor - The descriptor describing the resource to unpack.
  311. Start - Pointer to where the start value should be unpacked to.
  312. End - Pointer to where the end value should be unpacked to.
  313. Return Value:
  314. Returns the status of this operation.
  315. --*/
  316. {
  317. PAGED_CODE();
  318. switch (Descriptor->Type) {
  319. case CmResourceTypePort:
  320. case CmResourceTypeMemory:
  321. *Start = Descriptor->u.Generic.Start.QuadPart;
  322. *Length = Descriptor->u.Generic.Length;
  323. break;
  324. case CmResourceTypeInterrupt:
  325. *Start = Descriptor->u.Interrupt.Vector;
  326. *Length = 1;
  327. break;
  328. case CmResourceTypeDma:
  329. *Start = Descriptor->u.Dma.Channel;
  330. *Length = 1;
  331. break;
  332. case CmResourceTypeBusNumber:
  333. *Start = Descriptor->u.BusNumber.Start;
  334. *Length = Descriptor->u.BusNumber.Length;
  335. break;
  336. default:
  337. return STATUS_INVALID_PARAMETER;
  338. }
  339. return STATUS_SUCCESS;
  340. }
  341. NTSTATUS
  342. MfUpdateResource(
  343. IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
  344. IN ULONGLONG Start,
  345. IN ULONG Length
  346. )
  347. {
  348. PAGED_CODE();
  349. ASSERT(Resource);
  350. switch (Resource->Type) {
  351. case CmResourceTypePort:
  352. case CmResourceTypeMemory:
  353. Resource->u.Generic.Start.QuadPart = Start;
  354. Resource->u.Generic.Length = Length;
  355. break;
  356. case CmResourceTypeInterrupt:
  357. ASSERT(Start < MAXULONG);
  358. Resource->u.Interrupt.Vector = (ULONG)Start;
  359. break;
  360. case CmResourceTypeDma:
  361. ASSERT(Start < MAXULONG);
  362. Resource->u.Dma.Channel = (ULONG)Start;
  363. break;
  364. case CmResourceTypeBusNumber:
  365. ASSERT(Start < MAXULONG);
  366. Resource->u.BusNumber.Start = (ULONG)Start;
  367. Resource->u.BusNumber.Length = Length;
  368. break;
  369. default:
  370. return STATUS_INVALID_PARAMETER;
  371. }
  372. return STATUS_SUCCESS;
  373. }