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.

522 lines
12 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. //
  251. // Zero alignment is illegal.
  252. //
  253. if (*Alignment == 0) {
  254. *Alignment = 1;
  255. }
  256. return STATUS_SUCCESS;
  257. }
  258. NTSTATUS
  259. MfPackResource(
  260. IN PIO_RESOURCE_DESCRIPTOR Requirement,
  261. IN ULONGLONG Start,
  262. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
  263. )
  264. /*++
  265. Routine Description:
  266. This routine packs an resource descriptor.
  267. Arguments:
  268. Requirement - The requirement from which this resource was chosen.
  269. Start - The start value of the resource.
  270. Descriptor - Pointer to the descriptor to pack into.
  271. Return Value:
  272. Returns the status of this operation.
  273. --*/
  274. {
  275. PAGED_CODE();
  276. switch (Requirement->Type) {
  277. case CmResourceTypePort:
  278. case CmResourceTypeMemory:
  279. Descriptor->u.Generic.Start.QuadPart = Start;
  280. Descriptor->u.Generic.Length = Requirement->u.Generic.Length;
  281. break;
  282. case CmResourceTypeInterrupt:
  283. ASSERT(Start <= MAXULONG);
  284. Descriptor->u.Interrupt.Level = (ULONG)Start;
  285. Descriptor->u.Interrupt.Vector = (ULONG)Start;
  286. Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
  287. break;
  288. case CmResourceTypeDma:
  289. ASSERT(Start <= MAXULONG);
  290. Descriptor->u.Dma.Channel = (ULONG)Start;
  291. Descriptor->u.Dma.Port = 0;
  292. break;
  293. case CmResourceTypeBusNumber:
  294. ASSERT(Start <= MAXULONG);
  295. Descriptor->u.BusNumber.Start = (ULONG)Start;
  296. Descriptor->u.BusNumber.Length = Requirement->u.BusNumber.Length;
  297. break;
  298. default:
  299. return STATUS_INVALID_PARAMETER;
  300. }
  301. Descriptor->ShareDisposition = Requirement->ShareDisposition;
  302. Descriptor->Flags = Requirement->Flags;
  303. Descriptor->Type = Requirement->Type;
  304. return STATUS_SUCCESS;
  305. }
  306. NTSTATUS
  307. MfUnpackResource(
  308. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
  309. OUT PULONGLONG Start,
  310. OUT PULONG Length
  311. )
  312. /*++
  313. Routine Description:
  314. This routine unpacks a resource descriptor.
  315. Arguments:
  316. Descriptor - The descriptor describing the resource to unpack.
  317. Start - Pointer to where the start value should be unpacked to.
  318. End - Pointer to where the end value should be unpacked to.
  319. Return Value:
  320. Returns the status of this operation.
  321. --*/
  322. {
  323. PAGED_CODE();
  324. switch (Descriptor->Type) {
  325. case CmResourceTypePort:
  326. case CmResourceTypeMemory:
  327. *Start = Descriptor->u.Generic.Start.QuadPart;
  328. *Length = Descriptor->u.Generic.Length;
  329. break;
  330. case CmResourceTypeInterrupt:
  331. *Start = Descriptor->u.Interrupt.Vector;
  332. *Length = 1;
  333. break;
  334. case CmResourceTypeDma:
  335. *Start = Descriptor->u.Dma.Channel;
  336. *Length = 1;
  337. break;
  338. case CmResourceTypeBusNumber:
  339. *Start = Descriptor->u.BusNumber.Start;
  340. *Length = Descriptor->u.BusNumber.Length;
  341. break;
  342. default:
  343. return STATUS_INVALID_PARAMETER;
  344. }
  345. return STATUS_SUCCESS;
  346. }
  347. NTSTATUS
  348. MfUpdateResource(
  349. IN OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource,
  350. IN ULONGLONG Start,
  351. IN ULONG Length
  352. )
  353. {
  354. PAGED_CODE();
  355. ASSERT(Resource);
  356. switch (Resource->Type) {
  357. case CmResourceTypePort:
  358. case CmResourceTypeMemory:
  359. Resource->u.Generic.Start.QuadPart = Start;
  360. Resource->u.Generic.Length = Length;
  361. break;
  362. case CmResourceTypeInterrupt:
  363. ASSERT(Start < MAXULONG);
  364. Resource->u.Interrupt.Vector = (ULONG)Start;
  365. break;
  366. case CmResourceTypeDma:
  367. ASSERT(Start < MAXULONG);
  368. Resource->u.Dma.Channel = (ULONG)Start;
  369. break;
  370. case CmResourceTypeBusNumber:
  371. ASSERT(Start < MAXULONG);
  372. Resource->u.BusNumber.Start = (ULONG)Start;
  373. Resource->u.BusNumber.Length = Length;
  374. break;
  375. default:
  376. return STATUS_INVALID_PARAMETER;
  377. }
  378. return STATUS_SUCCESS;
  379. }