devres.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. devres.c
  5. Abstract:
  6. This module implements device resource requirement and allocation
  7. functionality.
  8. Author:
  9. Evan Green 2-Dec-2012
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/kernel.h>
  17. #include "iop.h"
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. //
  22. // Some resources need to be non-paged because they may be used by the paging
  23. // device during I/O transfers.
  24. //
  25. #define RESOURCE_TYPE_NON_PAGED(_ResourceType) \
  26. ((_ResourceType) == ResourceTypeDmaChannel)
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. #define RESOURCE_ALLOCATION_TAG 0x4C736552 // 'LseR'
  31. //
  32. // Set a sane limit on how big these allocations can get.
  33. //
  34. #define RESOURCE_MAX_ADDITIONAL_DATA 0x1000
  35. //
  36. // ------------------------------------------------------ Data Type Definitions
  37. //
  38. //
  39. // ----------------------------------------------- Internal Function Prototypes
  40. //
  41. VOID
  42. IopResourceAllocationWorker (
  43. PVOID Parameter
  44. );
  45. VOID
  46. IopDelayedResourceAssignmentWorker (
  47. PVOID Parameter
  48. );
  49. KSTATUS
  50. IopCreateAndInitializeResourceRequirement (
  51. PRESOURCE_REQUIREMENT RequirementTemplate,
  52. PRESOURCE_REQUIREMENT *NewRequirement
  53. );
  54. PSTR
  55. IopGetResourceTypeString (
  56. RESOURCE_TYPE Type
  57. );
  58. //
  59. // -------------------------------------------------------------------- Globals
  60. //
  61. //
  62. // Store the array of devices that were delayed until the initial enumeration
  63. // was complete.
  64. //
  65. PDEVICE *IoDelayedDevices;
  66. UINTN IoDelayedDeviceCount;
  67. //
  68. // ------------------------------------------------------------------ Functions
  69. //
  70. //
  71. // Resource requirement list support routines.
  72. //
  73. KERNEL_API
  74. PRESOURCE_REQUIREMENT_LIST
  75. IoCreateResourceRequirementList (
  76. VOID
  77. )
  78. /*++
  79. Routine Description:
  80. This routine creates a new empty resource requirement list.
  81. Arguments:
  82. None.
  83. Return Value:
  84. Returns a pointer to the new resource requirement list on success.
  85. NULL on allocation failure.
  86. --*/
  87. {
  88. PRESOURCE_REQUIREMENT_LIST List;
  89. List = MmAllocatePagedPool(sizeof(RESOURCE_REQUIREMENT_LIST),
  90. RESOURCE_ALLOCATION_TAG);
  91. if (List == NULL) {
  92. return NULL;
  93. }
  94. RtlZeroMemory(List, sizeof(RESOURCE_REQUIREMENT_LIST));
  95. INITIALIZE_LIST_HEAD(&(List->RequirementListHead));
  96. return List;
  97. }
  98. KERNEL_API
  99. VOID
  100. IoDestroyResourceRequirementList (
  101. PRESOURCE_REQUIREMENT_LIST ResourceRequirementList
  102. )
  103. /*++
  104. Routine Description:
  105. This routine releases the memory associated with a resource requirement
  106. list, and any items on that list.
  107. Arguments:
  108. ResourceRequirementList - Supplies a pointer to the resource requirement
  109. list to destroy.
  110. Return Value:
  111. None.
  112. --*/
  113. {
  114. PLIST_ENTRY CurrentEntry;
  115. PRESOURCE_REQUIREMENT ResourceRequirement;
  116. while (LIST_EMPTY(&(ResourceRequirementList->RequirementListHead)) ==
  117. FALSE) {
  118. CurrentEntry = ResourceRequirementList->RequirementListHead.Next;
  119. ResourceRequirement = LIST_VALUE(CurrentEntry,
  120. RESOURCE_REQUIREMENT,
  121. ListEntry);
  122. IoRemoveResourceRequirement(ResourceRequirement);
  123. }
  124. if (ResourceRequirementList->ListEntry.Next != NULL) {
  125. LIST_REMOVE(&(ResourceRequirementList->ListEntry));
  126. }
  127. MmFreePagedPool(ResourceRequirementList);
  128. return;
  129. }
  130. KERNEL_API
  131. KSTATUS
  132. IoCreateAndAddResourceRequirement (
  133. PRESOURCE_REQUIREMENT Requirement,
  134. PRESOURCE_REQUIREMENT_LIST ResourceRequirementList,
  135. PRESOURCE_REQUIREMENT *NewRequirement
  136. )
  137. /*++
  138. Routine Description:
  139. This routine creates a new resource requirement from the given template and
  140. inserts it into the given resource requirement list.
  141. Arguments:
  142. Requirement - Supplies a pointer to the resource requirement to use as a
  143. template. The memory passed in will not actually be used, a copy of the
  144. requirement will be created, initialized, and placed on the list.
  145. ResourceRequirementList - Supplies a pointer to the resource requirement
  146. list to add the requirement to.
  147. NewRequirement - Supplies an optional pointer to the resource requirement
  148. that was created. The system owns this memory, the caller should not
  149. attempt to free it directly.
  150. Return Value:
  151. STATUS_SUCCESS on success.
  152. STATUS_INVALID_PARAMETER if parameter validation failed.
  153. STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
  154. --*/
  155. {
  156. PRESOURCE_REQUIREMENT CreatedRequirement;
  157. KSTATUS Status;
  158. CreatedRequirement = NULL;
  159. Status = IopCreateAndInitializeResourceRequirement(Requirement,
  160. &CreatedRequirement);
  161. if (!KSUCCESS(Status)) {
  162. goto CreateAndAddResourceRequirementEnd;
  163. }
  164. //
  165. // Add the requirement to the end of the list.
  166. //
  167. INSERT_BEFORE(&(CreatedRequirement->ListEntry),
  168. &(ResourceRequirementList->RequirementListHead));
  169. Status = STATUS_SUCCESS;
  170. CreateAndAddResourceRequirementEnd:
  171. if (NewRequirement != NULL) {
  172. *NewRequirement = CreatedRequirement;
  173. }
  174. return Status;
  175. }
  176. KERNEL_API
  177. VOID
  178. IoRemoveResourceRequirement (
  179. PRESOURCE_REQUIREMENT Requirement
  180. )
  181. /*++
  182. Routine Description:
  183. This routine removes the given resource descriptor from its resource list
  184. and frees the memory associated with that descriptor.
  185. Arguments:
  186. Requirement - Supplies a pointer to the resource requirement to remove and
  187. destroy.
  188. Return Value:
  189. None.
  190. --*/
  191. {
  192. PRESOURCE_REQUIREMENT Alternative;
  193. PLIST_ENTRY CurrentEntry;
  194. //
  195. // Loop through and destroy all alternatives to this resource requirement.
  196. //
  197. CurrentEntry = Requirement->AlternativeListEntry.Next;
  198. while (CurrentEntry != &(Requirement->AlternativeListEntry)) {
  199. Alternative = LIST_VALUE(CurrentEntry,
  200. RESOURCE_REQUIREMENT,
  201. AlternativeListEntry);
  202. //
  203. // It's important to move the list entry before the alternative is
  204. // destroyed!
  205. //
  206. CurrentEntry = CurrentEntry->Next;
  207. IoRemoveResourceRequirementAlternative(Alternative);
  208. }
  209. ASSERT(LIST_EMPTY(&(Requirement->AlternativeListEntry)) != FALSE);
  210. LIST_REMOVE(&(Requirement->ListEntry));
  211. MmFreePagedPool(Requirement);
  212. return;
  213. }
  214. KERNEL_API
  215. KSTATUS
  216. IoCreateAndAddResourceRequirementAlternative (
  217. PRESOURCE_REQUIREMENT Alternative,
  218. PRESOURCE_REQUIREMENT Requirement
  219. )
  220. /*++
  221. Routine Description:
  222. This routine creates a new resource requirement alternative from the given
  223. template and inserts it into the given resource requirement alternative
  224. list.
  225. Arguments:
  226. Alternative - Supplies a pointer to the resource requirement to use as a
  227. template. The memory passed in will not actually be used, a copy of the
  228. requirement will be created, initialized, and placed on the list.
  229. Requirement - Supplies a pointer to the resource requirement to add the
  230. alternative to.
  231. Return Value:
  232. STATUS_SUCCESS on success.
  233. STATUS_INVALID_PARAMETER if parameter validation failed.
  234. STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
  235. --*/
  236. {
  237. PRESOURCE_REQUIREMENT NewRequirement;
  238. KSTATUS Status;
  239. Status = IopCreateAndInitializeResourceRequirement(Alternative,
  240. &NewRequirement);
  241. if (!KSUCCESS(Status)) {
  242. goto CreateAndAddResourceRequirementAlternativeEnd;
  243. }
  244. //
  245. // Add the alternative to the end of the list.
  246. //
  247. INSERT_BEFORE(&(NewRequirement->AlternativeListEntry),
  248. &(Requirement->AlternativeListEntry));
  249. Status = STATUS_SUCCESS;
  250. CreateAndAddResourceRequirementAlternativeEnd:
  251. return Status;
  252. }
  253. KERNEL_API
  254. VOID
  255. IoRemoveResourceRequirementAlternative (
  256. PRESOURCE_REQUIREMENT Alternative
  257. )
  258. /*++
  259. Routine Description:
  260. This routine removes the given resource requirement alternative from its
  261. resource list and frees the memory associated with that descriptor.
  262. Arguments:
  263. Alternative - Supplies a pointer to the resource requirement alternative
  264. to remove and destroy.
  265. Return Value:
  266. None.
  267. --*/
  268. {
  269. //
  270. // This had better be an alternative and not a first requirement.
  271. //
  272. ASSERT(Alternative->ListEntry.Next == NULL);
  273. LIST_REMOVE(&(Alternative->AlternativeListEntry));
  274. MmFreePagedPool(Alternative);
  275. return;
  276. }
  277. KERNEL_API
  278. KSTATUS
  279. IoCreateAndAddInterruptVectorsForLines (
  280. PRESOURCE_CONFIGURATION_LIST ConfigurationList,
  281. PRESOURCE_REQUIREMENT VectorTemplate
  282. )
  283. /*++
  284. Routine Description:
  285. This routine creates a new vector resource requirement for each interrupt
  286. line requirement in the given configuration list.
  287. Arguments:
  288. ConfigurationList - Supplies a pointer to the resource configuration list
  289. to iterate through.
  290. VectorTemplate - Supplies a pointer to a template to use when creating the
  291. vector resource requirements.
  292. Return Value:
  293. STATUS_SUCCESS on success.
  294. STATUS_INVALID_PARAMETER if parameter validation failed.
  295. STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
  296. --*/
  297. {
  298. ULONGLONG LineCharacteristics;
  299. PRESOURCE_REQUIREMENT NextRequirement;
  300. PRESOURCE_REQUIREMENT Requirement;
  301. PRESOURCE_REQUIREMENT_LIST RequirementList;
  302. KSTATUS Status;
  303. ULONGLONG VectorCharacteristics;
  304. //
  305. // Loop through all configuration lists.
  306. //
  307. if (ConfigurationList == NULL) {
  308. Status = STATUS_SUCCESS;
  309. goto CreateAndAddInterruptVectorsForLinesEnd;
  310. }
  311. RequirementList = IoGetNextResourceConfiguration(ConfigurationList, NULL);
  312. while (RequirementList != NULL) {
  313. //
  314. // Loop through every requirement in the list.
  315. //
  316. Requirement = IoGetNextResourceRequirement(RequirementList, NULL);
  317. while (Requirement != NULL) {
  318. //
  319. // Get the next resource requirement.
  320. //
  321. NextRequirement = IoGetNextResourceRequirement(RequirementList,
  322. Requirement);
  323. //
  324. // Skip the requirement if it is not an interrupt line.
  325. //
  326. if (Requirement->Type != ResourceTypeInterruptLine) {
  327. Requirement = NextRequirement;
  328. continue;
  329. }
  330. //
  331. // The requirement is an interrupt line. Add a vector requirement
  332. // based on the template.
  333. //
  334. VectorCharacteristics = 0;
  335. LineCharacteristics = Requirement->Characteristics;
  336. if ((LineCharacteristics & INTERRUPT_LINE_ACTIVE_LOW) != 0) {
  337. VectorCharacteristics |= INTERRUPT_VECTOR_ACTIVE_LOW;
  338. }
  339. if ((LineCharacteristics & INTERRUPT_LINE_ACTIVE_HIGH) != 0) {
  340. VectorCharacteristics |= INTERRUPT_VECTOR_ACTIVE_HIGH;
  341. }
  342. if ((LineCharacteristics & INTERRUPT_LINE_EDGE_TRIGGERED) != 0) {
  343. VectorCharacteristics |= INTERRUPT_VECTOR_EDGE_TRIGGERED;
  344. }
  345. //
  346. // Secondary interrupt lines have run-levels that may not
  347. // correspond in a direct way to their interrupt vector. These
  348. // types of vectors cannot be shared as it might create a conflict
  349. // of different run-levels for the same vector.
  350. //
  351. if ((LineCharacteristics & INTERRUPT_LINE_SECONDARY) != 0) {
  352. VectorTemplate->Flags |= RESOURCE_FLAG_NOT_SHAREABLE;
  353. }
  354. VectorTemplate->Characteristics = VectorCharacteristics;
  355. VectorTemplate->OwningRequirement = Requirement;
  356. Status = IoCreateAndAddResourceRequirement(VectorTemplate,
  357. RequirementList,
  358. NULL);
  359. if (!KSUCCESS(Status)) {
  360. goto CreateAndAddInterruptVectorsForLinesEnd;
  361. }
  362. Requirement = NextRequirement;
  363. }
  364. //
  365. // Get the next possible resource configuration.
  366. //
  367. RequirementList = IoGetNextResourceConfiguration(ConfigurationList,
  368. RequirementList);
  369. }
  370. Status = STATUS_SUCCESS;
  371. CreateAndAddInterruptVectorsForLinesEnd:
  372. return Status;
  373. }
  374. KERNEL_API
  375. PRESOURCE_REQUIREMENT
  376. IoGetNextResourceRequirement (
  377. PRESOURCE_REQUIREMENT_LIST ResourceRequirementList,
  378. PRESOURCE_REQUIREMENT CurrentEntry
  379. )
  380. /*++
  381. Routine Description:
  382. This routine returns a pointer to the next resource requirment in the
  383. resource requirement list.
  384. Arguments:
  385. ResourceRequirementList - Supplies a pointer to the resource requirement
  386. list to iterate through.
  387. CurrentEntry - Supplies an optional pointer to the previous resource
  388. requirement. If supplied, the function will return the resource
  389. requirement immediately after this one in the list. If NULL is
  390. supplied, this routine will return the first resource requirement in the
  391. list.
  392. Return Value:
  393. Returns a pointer to the next resource requirement in the given list on
  394. success, or NULL if the last resource requirement was reached.
  395. --*/
  396. {
  397. PLIST_ENTRY NextEntry;
  398. if (CurrentEntry != NULL) {
  399. NextEntry = CurrentEntry->ListEntry.Next;
  400. } else {
  401. NextEntry = ResourceRequirementList->RequirementListHead.Next;
  402. }
  403. if (NextEntry == &(ResourceRequirementList->RequirementListHead)) {
  404. return NULL;
  405. }
  406. return LIST_VALUE(NextEntry, RESOURCE_REQUIREMENT, ListEntry);
  407. }
  408. KERNEL_API
  409. PRESOURCE_REQUIREMENT
  410. IoGetNextResourceRequirementAlternative (
  411. PRESOURCE_REQUIREMENT ResourceRequirement,
  412. PRESOURCE_REQUIREMENT CurrentEntry
  413. )
  414. /*++
  415. Routine Description:
  416. This routine returns a pointer to the next resource requirment alternative
  417. in the alternative list for the requirement.
  418. Arguments:
  419. ResourceRequirement - Supplies a pointer to the resource requirement at
  420. the head of the list.
  421. CurrentEntry - Supplies an optional pointer to the current requirement
  422. alternative.
  423. Return Value:
  424. Returns a pointer to the next resource requirement alternative in the list
  425. on success, or NULL if the last resource requirement alternative was
  426. reached.
  427. --*/
  428. {
  429. PLIST_ENTRY NextEntry;
  430. if (CurrentEntry != NULL) {
  431. NextEntry = CurrentEntry->AlternativeListEntry.Next;
  432. } else {
  433. NextEntry = ResourceRequirement->AlternativeListEntry.Next;
  434. }
  435. if (NextEntry == &(ResourceRequirement->AlternativeListEntry)) {
  436. return NULL;
  437. }
  438. return LIST_VALUE(NextEntry, RESOURCE_REQUIREMENT, AlternativeListEntry);
  439. }
  440. //
  441. // Resource configuration list routines.
  442. //
  443. KERNEL_API
  444. PRESOURCE_CONFIGURATION_LIST
  445. IoCreateResourceConfigurationList (
  446. PRESOURCE_REQUIREMENT_LIST FirstConfiguration
  447. )
  448. /*++
  449. Routine Description:
  450. This routine creates a new resource configuration list. A resource
  451. configuration list is a collection of resource requirement lists, arranged
  452. from most desirable to least desirable. The system attempts selects the
  453. most desirable resource configuration that can be afforded.
  454. Arguments:
  455. FirstConfiguration - Supplies an optional pointer to the first configuration
  456. to put on the list. If NULL is supplied, an empty resource
  457. configuration list will be created.
  458. Return Value:
  459. Returns a pointer to the new resource configuration list on success.
  460. NULL on allocation failure.
  461. --*/
  462. {
  463. PRESOURCE_CONFIGURATION_LIST List;
  464. List = MmAllocatePagedPool(sizeof(RESOURCE_CONFIGURATION_LIST),
  465. RESOURCE_ALLOCATION_TAG);
  466. if (List == NULL) {
  467. return NULL;
  468. }
  469. RtlZeroMemory(List, sizeof(RESOURCE_CONFIGURATION_LIST));
  470. INITIALIZE_LIST_HEAD(&(List->RequirementListListHead));
  471. if (FirstConfiguration != NULL) {
  472. INSERT_AFTER(&(FirstConfiguration->ListEntry),
  473. &(List->RequirementListListHead));
  474. }
  475. return List;
  476. }
  477. KERNEL_API
  478. VOID
  479. IoDestroyResourceConfigurationList (
  480. PRESOURCE_CONFIGURATION_LIST ResourceConfigurationList
  481. )
  482. /*++
  483. Routine Description:
  484. This routine releases the memory associated with a resource configuration
  485. list, and any resource requirement lists it may contain.
  486. Arguments:
  487. ResourceConfigurationList - Supplies a pointer to the resource configuration
  488. list to destroy.
  489. Return Value:
  490. None.
  491. --*/
  492. {
  493. PLIST_ENTRY CurrentEntry;
  494. PRESOURCE_REQUIREMENT_LIST RequirementList;
  495. while (LIST_EMPTY(&(ResourceConfigurationList->RequirementListListHead)) ==
  496. FALSE) {
  497. CurrentEntry = ResourceConfigurationList->RequirementListListHead.Next;
  498. RequirementList = LIST_VALUE(CurrentEntry,
  499. RESOURCE_REQUIREMENT_LIST,
  500. ListEntry);
  501. IoDestroyResourceRequirementList(RequirementList);
  502. }
  503. MmFreePagedPool(ResourceConfigurationList);
  504. return;
  505. }
  506. KERNEL_API
  507. KSTATUS
  508. IoAddResourceConfiguration (
  509. PRESOURCE_REQUIREMENT_LIST Configuration,
  510. PRESOURCE_REQUIREMENT_LIST ConfigurationToInsertAfter,
  511. PRESOURCE_CONFIGURATION_LIST ConfigurationList
  512. )
  513. /*++
  514. Routine Description:
  515. This routine inserts an initialized resource configuration into a
  516. configuration list.
  517. Arguments:
  518. Configuration - Supplies a pointer to the resource configuration to insert
  519. into the list.
  520. ConfigurationToInsertAfter - Supplies an optional pointer indicating the
  521. location in the list to insert the configuration. If this pointer is
  522. supplied, the configuration will be inserted immediate after this
  523. parameter in the list. If NULL is supplied, the configuration will be
  524. added to the end of the list.
  525. ConfigurationList - Supplies a pointer to the list to add the configuration
  526. to.
  527. Return Value:
  528. Status code.
  529. --*/
  530. {
  531. ASSERT(Configuration->ListEntry.Next == NULL);
  532. if (ConfigurationToInsertAfter != NULL) {
  533. INSERT_AFTER(&(Configuration->ListEntry),
  534. &(ConfigurationToInsertAfter->ListEntry));
  535. } else {
  536. INSERT_BEFORE(&(Configuration->ListEntry),
  537. &(ConfigurationList->RequirementListListHead));
  538. }
  539. return STATUS_SUCCESS;
  540. }
  541. KERNEL_API
  542. VOID
  543. IoRemoveResourceConfiguration (
  544. PRESOURCE_REQUIREMENT_LIST Configuration,
  545. PRESOURCE_CONFIGURATION_LIST ConfigurationList
  546. )
  547. /*++
  548. Routine Description:
  549. This routine removes the given resource descriptor from its resource list.
  550. It does not free the memory associated with the configuration.
  551. Arguments:
  552. Configuration - Supplies a pointer to the configuration to remove.
  553. ConfigurationList - Supplies a pointer to the configuration list to remove
  554. the configuration from.
  555. Return Value:
  556. None.
  557. --*/
  558. {
  559. ASSERT(Configuration->ListEntry.Next != NULL);
  560. LIST_REMOVE(&(Configuration->ListEntry));
  561. Configuration->ListEntry.Next = NULL;
  562. return;
  563. }
  564. KERNEL_API
  565. PRESOURCE_REQUIREMENT_LIST
  566. IoGetNextResourceConfiguration (
  567. PRESOURCE_CONFIGURATION_LIST ConfigurationList,
  568. PRESOURCE_REQUIREMENT_LIST CurrentEntry
  569. )
  570. /*++
  571. Routine Description:
  572. This routine returns a pointer to the next resource configuration in the
  573. resource configuration list.
  574. Arguments:
  575. ConfigurationList - Supplies a pointer to the resource configuration list
  576. to iterate through.
  577. CurrentEntry - Supplies an optional pointer to the previous resource
  578. requirement list. If supplied, the function will return the
  579. configuration immediately after this one in the list. If NULL is
  580. supplied, this routine will return the first configuration in the
  581. list.
  582. Return Value:
  583. Returns a pointer to the next resource configuration in the given list on
  584. success, or NULL if the last resource requirement was reached.
  585. --*/
  586. {
  587. PLIST_ENTRY NextEntry;
  588. if (CurrentEntry != NULL) {
  589. NextEntry = CurrentEntry->ListEntry.Next;
  590. } else {
  591. NextEntry = ConfigurationList->RequirementListListHead.Next;
  592. }
  593. if (NextEntry == &(ConfigurationList->RequirementListListHead)) {
  594. return NULL;
  595. }
  596. return LIST_VALUE(NextEntry, RESOURCE_REQUIREMENT_LIST, ListEntry);
  597. }
  598. //
  599. // Resource allocation list support routines.
  600. //
  601. KERNEL_API
  602. PRESOURCE_ALLOCATION_LIST
  603. IoCreateResourceAllocationList (
  604. VOID
  605. )
  606. /*++
  607. Routine Description:
  608. This routine creates a new empty resource allocation list.
  609. Arguments:
  610. None.
  611. Return Value:
  612. Returns a pointer to the new resource allocation list on success.
  613. NULL on allocation failure.
  614. --*/
  615. {
  616. PRESOURCE_ALLOCATION_LIST List;
  617. List = MmAllocatePagedPool(sizeof(PRESOURCE_ALLOCATION_LIST),
  618. RESOURCE_ALLOCATION_TAG);
  619. if (List == NULL) {
  620. return NULL;
  621. }
  622. RtlZeroMemory(List, sizeof(PRESOURCE_ALLOCATION_LIST));
  623. INITIALIZE_LIST_HEAD(&(List->AllocationListHead));
  624. return List;
  625. }
  626. KERNEL_API
  627. VOID
  628. IoDestroyResourceAllocationList (
  629. PRESOURCE_ALLOCATION_LIST ResourceAllocationList
  630. )
  631. /*++
  632. Routine Description:
  633. This routine releases the memory associated with a resource allocation
  634. list, and any items on that list.
  635. Arguments:
  636. ResourceAllocationList - Supplies a pointer to the resource allocation
  637. list to destroy.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. PLIST_ENTRY CurrentEntry;
  643. PRESOURCE_ALLOCATION ResourceAllocation;
  644. while (LIST_EMPTY(&(ResourceAllocationList->AllocationListHead)) ==
  645. FALSE) {
  646. CurrentEntry = ResourceAllocationList->AllocationListHead.Next;
  647. ResourceAllocation = LIST_VALUE(CurrentEntry,
  648. RESOURCE_ALLOCATION,
  649. ListEntry);
  650. IoRemoveResourceAllocation(ResourceAllocation, ResourceAllocationList);
  651. }
  652. MmFreePagedPool(ResourceAllocationList);
  653. return;
  654. }
  655. KERNEL_API
  656. KSTATUS
  657. IoCreateAndAddResourceAllocation (
  658. PRESOURCE_ALLOCATION Allocation,
  659. PRESOURCE_ALLOCATION_LIST ResourceAllocationList
  660. )
  661. /*++
  662. Routine Description:
  663. This routine creates a new resource allocation from the given template and
  664. inserts it into the given resource allocation list.
  665. Arguments:
  666. Allocation - Supplies a pointer to the resource allocation to use as a
  667. template. The memory passed in will not actually be used, a copy of the
  668. allocation will be created, initialized, and placed on the list.
  669. ResourceAllocationList - Supplies a pointer to the resource allocation
  670. list to add the allocation to.
  671. Return Value:
  672. STATUS_SUCCESS on success.
  673. STATUS_INVALID_PARAMETER if parameter validation failed.
  674. STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
  675. --*/
  676. {
  677. UINTN AllocationSize;
  678. UINTN DataSize;
  679. PRESOURCE_ALLOCATION NewAllocation;
  680. KSTATUS Status;
  681. //
  682. // Check parameters.
  683. //
  684. if ((Allocation->Type == ResourceTypeInvalid) ||
  685. (Allocation->Type >= ResourceTypeCount)) {
  686. Status = STATUS_INVALID_PARAMETER;
  687. goto CreateAndAddResourceAllocationEnd;
  688. }
  689. DataSize = Allocation->DataSize;
  690. if (DataSize > RESOURCE_MAX_ADDITIONAL_DATA) {
  691. Status = STATUS_INVALID_PARAMETER;
  692. goto CreateAndAddResourceAllocationEnd;
  693. }
  694. //
  695. // Create the new resource allocation.
  696. //
  697. AllocationSize = sizeof(RESOURCE_ALLOCATION) + DataSize;
  698. if (RESOURCE_TYPE_NON_PAGED(Allocation->Type)) {
  699. NewAllocation = MmAllocateNonPagedPool(AllocationSize,
  700. RESOURCE_ALLOCATION_TAG);
  701. } else {
  702. NewAllocation = MmAllocatePagedPool(AllocationSize,
  703. RESOURCE_ALLOCATION_TAG);
  704. }
  705. if (NewAllocation == NULL) {
  706. Status = STATUS_INSUFFICIENT_RESOURCES;
  707. goto CreateAndAddResourceAllocationEnd;
  708. }
  709. RtlZeroMemory(NewAllocation, sizeof(RESOURCE_ALLOCATION));
  710. NewAllocation->Type = Allocation->Type;
  711. NewAllocation->Allocation = Allocation->Allocation;
  712. NewAllocation->Length = Allocation->Length;
  713. NewAllocation->Characteristics = Allocation->Characteristics;
  714. NewAllocation->Flags = Allocation->Flags;
  715. NewAllocation->OwningAllocation = Allocation->OwningAllocation;
  716. NewAllocation->Provider = Allocation->Provider;
  717. if (DataSize != 0) {
  718. NewAllocation->Data = NewAllocation + 1;
  719. NewAllocation->DataSize = DataSize;
  720. RtlCopyMemory(NewAllocation->Data, Allocation->Data, DataSize);
  721. }
  722. //
  723. // Add the allocation to the end of the list.
  724. //
  725. INSERT_BEFORE(&(NewAllocation->ListEntry),
  726. &(ResourceAllocationList->AllocationListHead));
  727. Status = STATUS_SUCCESS;
  728. CreateAndAddResourceAllocationEnd:
  729. return Status;
  730. }
  731. KERNEL_API
  732. VOID
  733. IoRemoveResourceAllocation (
  734. PRESOURCE_ALLOCATION Allocation,
  735. PRESOURCE_ALLOCATION_LIST ResourceAllocationList
  736. )
  737. /*++
  738. Routine Description:
  739. This routine removes the given resource descriptor from its resource list
  740. and frees the memory associated with that descriptor.
  741. Arguments:
  742. Allocation - Supplies a pointer to the allocation to remove.
  743. ResourceAllocationList - Supplies a pointer to the list to remove the
  744. allocation from.
  745. Return Value:
  746. None.
  747. --*/
  748. {
  749. ASSERT(ResourceAllocationList != NULL);
  750. LIST_REMOVE(&(Allocation->ListEntry));
  751. if (RESOURCE_TYPE_NON_PAGED(Allocation->Type)) {
  752. MmFreeNonPagedPool(Allocation);
  753. } else {
  754. MmFreePagedPool(Allocation);
  755. }
  756. return;
  757. }
  758. KERNEL_API
  759. PRESOURCE_ALLOCATION
  760. IoGetNextResourceAllocation (
  761. PRESOURCE_ALLOCATION_LIST ResourceAllocationList,
  762. PRESOURCE_ALLOCATION CurrentEntry
  763. )
  764. /*++
  765. Routine Description:
  766. This routine returns a pointer to the next resource allocation in the
  767. resource allocation list.
  768. Arguments:
  769. ResourceAllocationList - Supplies a pointer to the resource allocation
  770. list to iterate through.
  771. CurrentEntry - Supplies an optional pointer to the previous resource
  772. allocation. If supplied, the function will return the resource
  773. allocation immediately after this one in the list. If NULL is
  774. supplied, this routine will return the first resource allocation in the
  775. list.
  776. Return Value:
  777. Returns a pointer to the next resource allocation in the given list on
  778. success, or NULL if the last resource allocation was reached.
  779. --*/
  780. {
  781. PLIST_ENTRY NextEntry;
  782. if (ResourceAllocationList == NULL) {
  783. return NULL;
  784. }
  785. if (CurrentEntry != NULL) {
  786. NextEntry = CurrentEntry->ListEntry.Next;
  787. } else {
  788. NextEntry = ResourceAllocationList->AllocationListHead.Next;
  789. }
  790. if (NextEntry == &(ResourceAllocationList->AllocationListHead)) {
  791. return NULL;
  792. }
  793. return LIST_VALUE(NextEntry, RESOURCE_ALLOCATION, ListEntry);
  794. }
  795. KERNEL_API
  796. VOID
  797. IoDebugPrintResourceConfigurationList (
  798. PRESOURCE_CONFIGURATION_LIST ConfigurationList
  799. )
  800. /*++
  801. Routine Description:
  802. This routine prints a resource configuration list out to the debugger.
  803. Arguments:
  804. ConfigurationList - Supplies a pointer to the resource configuration list to
  805. print.
  806. Return Value:
  807. None.
  808. --*/
  809. {
  810. PLIST_ENTRY CurrentEntry;
  811. PRESOURCE_REQUIREMENT_LIST RequirementList;
  812. RtlDebugPrint("Resource Configuration List at %x:\n", ConfigurationList);
  813. CurrentEntry = ConfigurationList->RequirementListListHead.Next;
  814. while (CurrentEntry != &(ConfigurationList->RequirementListListHead)) {
  815. RequirementList = LIST_VALUE(CurrentEntry,
  816. RESOURCE_REQUIREMENT_LIST,
  817. ListEntry);
  818. CurrentEntry = CurrentEntry->Next;
  819. IoDebugPrintResourceRequirementList(1, RequirementList);
  820. }
  821. return;
  822. }
  823. KERNEL_API
  824. VOID
  825. IoDebugPrintResourceRequirementList (
  826. ULONG IndentationLevel,
  827. PRESOURCE_REQUIREMENT_LIST RequirementList
  828. )
  829. /*++
  830. Routine Description:
  831. This routine prints a resource requirement list out to the debugger.
  832. Arguments:
  833. IndentationLevel - Supplies the indentation level to print this list
  834. at. Supply 0 if this function is called directly.
  835. RequirementList - Supplies a pointer to the resource requirement list to
  836. print.
  837. Return Value:
  838. None.
  839. --*/
  840. {
  841. PLIST_ENTRY CurrentEntry;
  842. ULONG IndentationIndex;
  843. PRESOURCE_REQUIREMENT Requirement;
  844. for (IndentationIndex = 0;
  845. IndentationIndex < IndentationLevel;
  846. IndentationIndex += 1) {
  847. RtlDebugPrint(" ");
  848. }
  849. RtlDebugPrint("Resource Requirement List at %x:\n", RequirementList);
  850. CurrentEntry = RequirementList->RequirementListHead.Next;
  851. while (CurrentEntry != &(RequirementList->RequirementListHead)) {
  852. Requirement = LIST_VALUE(CurrentEntry, RESOURCE_REQUIREMENT, ListEntry);
  853. CurrentEntry = CurrentEntry->Next;
  854. IoDebugPrintResourceRequirement(IndentationLevel + 1, Requirement);
  855. }
  856. return;
  857. }
  858. KERNEL_API
  859. VOID
  860. IoDebugPrintResourceRequirement (
  861. ULONG IndentationLevel,
  862. PRESOURCE_REQUIREMENT Requirement
  863. )
  864. /*++
  865. Routine Description:
  866. This routine prints a resource requirement out to the debugger.
  867. Arguments:
  868. IndentationLevel - Supplies the indentation level to print this requirement
  869. at. Supply 0 if this function is called directly.
  870. Requirement - Supplies a pointer to the resource requirement to print.
  871. Return Value:
  872. None.
  873. --*/
  874. {
  875. PRESOURCE_REQUIREMENT Alternative;
  876. PLIST_ENTRY CurrentEntry;
  877. ULONG IndentationIndex;
  878. PSTR ResourceType;
  879. for (IndentationIndex = 0;
  880. IndentationIndex < IndentationLevel;
  881. IndentationIndex += 1) {
  882. RtlDebugPrint(" ");
  883. }
  884. //
  885. // Get the resource type.
  886. //
  887. ResourceType = IopGetResourceTypeString(Requirement->Type);
  888. RtlDebugPrint("%x %16s: From %08I64x to %08I64x, Len %I64x, Align %08I64x, "
  889. "Char: %I64x, Flags: %I64x, Owner: %08x\n",
  890. Requirement,
  891. ResourceType,
  892. Requirement->Minimum,
  893. Requirement->Maximum,
  894. Requirement->Length,
  895. Requirement->Alignment,
  896. Requirement->Characteristics,
  897. Requirement->Flags,
  898. Requirement->OwningRequirement);
  899. //
  900. // If the requirement is not attached to a resource requirement list,
  901. // don't try to traverse alternatives.
  902. //
  903. if (Requirement->ListEntry.Next == NULL) {
  904. return;
  905. }
  906. //
  907. // Loop through and recursively print out all alternatives.
  908. //
  909. CurrentEntry = Requirement->AlternativeListEntry.Next;
  910. while (CurrentEntry != &(Requirement->AlternativeListEntry)) {
  911. Alternative = LIST_VALUE(CurrentEntry,
  912. RESOURCE_REQUIREMENT,
  913. AlternativeListEntry);
  914. CurrentEntry = CurrentEntry->Next;
  915. IoDebugPrintResourceRequirement(IndentationLevel + 1, Alternative);
  916. }
  917. return;
  918. }
  919. KERNEL_API
  920. VOID
  921. IoDebugPrintResourceAllocationList (
  922. ULONG IndentationLevel,
  923. PRESOURCE_ALLOCATION_LIST AllocationList
  924. )
  925. /*++
  926. Routine Description:
  927. This routine prints a resource allocation list out to the debugger.
  928. Arguments:
  929. IndentationLevel - Supplies the indentation level to print this list
  930. at. Supply 0 if this function is called directly.
  931. AllocationList - Supplies a pointer to the resource allocation list to
  932. print.
  933. Return Value:
  934. None.
  935. --*/
  936. {
  937. PRESOURCE_ALLOCATION Allocation;
  938. PLIST_ENTRY CurrentEntry;
  939. ULONG IndentationIndex;
  940. for (IndentationIndex = 0;
  941. IndentationIndex < IndentationLevel;
  942. IndentationIndex += 1) {
  943. RtlDebugPrint(" ");
  944. }
  945. RtlDebugPrint("Resource Allocation List at %x:\n", AllocationList);
  946. CurrentEntry = AllocationList->AllocationListHead.Next;
  947. while (CurrentEntry != &(AllocationList->AllocationListHead)) {
  948. Allocation = LIST_VALUE(CurrentEntry, RESOURCE_ALLOCATION, ListEntry);
  949. CurrentEntry = CurrentEntry->Next;
  950. IoDebugPrintResourceAllocation(IndentationLevel + 1, Allocation);
  951. }
  952. return;
  953. }
  954. KERNEL_API
  955. VOID
  956. IoDebugPrintResourceAllocation (
  957. ULONG IndentationLevel,
  958. PRESOURCE_ALLOCATION Allocation
  959. )
  960. /*++
  961. Routine Description:
  962. This routine prints a resource allocation out to the debugger.
  963. Arguments:
  964. IndentationLevel - Supplies the indentation level to print this allocation
  965. at. Supply 0 if this function is called directly.
  966. Allocation - Supplies a pointer to the resource allocation to print.
  967. Return Value:
  968. None.
  969. --*/
  970. {
  971. ULONG IndentationIndex;
  972. PSTR ResourceType;
  973. for (IndentationIndex = 0;
  974. IndentationIndex < IndentationLevel;
  975. IndentationIndex += 1) {
  976. RtlDebugPrint(" ");
  977. }
  978. ResourceType = IopGetResourceTypeString(Allocation->Type);
  979. RtlDebugPrint("%08x %16s: %08I64x, Len %08I64x, Char %I64x, Flags %I64x "
  980. "Owner %08x ",
  981. Allocation,
  982. ResourceType,
  983. Allocation->Allocation,
  984. Allocation->Length,
  985. Allocation->Characteristics,
  986. Allocation->Flags,
  987. Allocation->OwningAllocation);
  988. if ((Allocation->Flags & RESOURCE_FLAG_NOT_SHAREABLE) != 0) {
  989. RtlDebugPrint("NotShared ");
  990. }
  991. RtlDebugPrint("\n");
  992. return;
  993. }
  994. KSTATUS
  995. IopQueueResourceAssignment (
  996. PDEVICE Device
  997. )
  998. /*++
  999. Routine Description:
  1000. This routine puts this device in the resource assignment queue.
  1001. Arguments:
  1002. Device - Supplies a pointer to the device to queue for resource assignment.
  1003. Return Value:
  1004. Status code indicating whether or not the device was successfully queued.
  1005. (Not that it successfully made it through the queue or was processed in
  1006. any way).
  1007. --*/
  1008. {
  1009. DEVICE_STATE OldState;
  1010. KSTATUS Status;
  1011. //
  1012. // If the device has no resource requirements and no boot resources, move
  1013. // the device straight to resources assigned.
  1014. //
  1015. if ((Device->ResourceRequirements == NULL) &&
  1016. (Device->BootResources == NULL)) {
  1017. Status = STATUS_SUCCESS;
  1018. IopSetDeviceState(Device, DeviceResourcesAssigned);
  1019. goto QueueResourceAssignmentEnd;
  1020. }
  1021. //
  1022. // Set the state as if the operation was successful so that this routine is
  1023. // not racing with the worker to set the state later.
  1024. //
  1025. OldState = Device->State;
  1026. IopSetDeviceState(Device, DeviceResourceAssignmentQueued);
  1027. RtlAtomicAdd(&IoDeviceWorkItemsQueued, 1);
  1028. Status = KeCreateAndQueueWorkItem(IoResourceAllocationWorkQueue,
  1029. WorkPriorityNormal,
  1030. IopResourceAllocationWorker,
  1031. Device);
  1032. //
  1033. // If it didn't work, set the state back to what it was before, resource
  1034. // assignment work was not queued.
  1035. //
  1036. if (!KSUCCESS(Status)) {
  1037. RtlAtomicAdd(&IoDeviceWorkItemsQueued, -1);
  1038. IopSetDeviceState(Device, OldState);
  1039. IopSetDeviceProblem(Device,
  1040. DeviceProblemFailedToQueueResourceAssignmentWork,
  1041. Status);
  1042. }
  1043. QueueResourceAssignmentEnd:
  1044. return Status;
  1045. }
  1046. KSTATUS
  1047. IopQueueDelayedResourceAssignment (
  1048. VOID
  1049. )
  1050. /*++
  1051. Routine Description:
  1052. This routine queues resource assignment for devices that were delayed to
  1053. allow devices with boot resources to go first.
  1054. Arguments:
  1055. None.
  1056. Return Value:
  1057. Status code.
  1058. --*/
  1059. {
  1060. KSTATUS Status;
  1061. Status = KeCreateAndQueueWorkItem(IoResourceAllocationWorkQueue,
  1062. WorkPriorityNormal,
  1063. IopDelayedResourceAssignmentWorker,
  1064. NULL);
  1065. return Status;
  1066. }
  1067. //
  1068. // --------------------------------------------------------- Internal Functions
  1069. //
  1070. VOID
  1071. IopResourceAllocationWorker (
  1072. PVOID Parameter
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This routine is workhorse function fo the resource allocation work queue.
  1077. It attempts to satisfy the resource requirements of a device.
  1078. Arguments:
  1079. Parameter - Supplies the work item parameter, which in this case is a
  1080. pointer to the device to try and allocate resource for.
  1081. Return Value:
  1082. None. If the allocation is successful, the state in the device will be
  1083. advanced and work will be queued to start the device. If the allocation
  1084. fails, the device will be marked with a problem code.
  1085. --*/
  1086. {
  1087. PDEVICE Device;
  1088. UINTN OldWorkItemCount;
  1089. KSTATUS Status;
  1090. Device = (PDEVICE)Parameter;
  1091. //
  1092. // Attempt to satisfy the resource requirements of the device.
  1093. //
  1094. Status = IopProcessResourceRequirements(Device);
  1095. if (!KSUCCESS(Status)) {
  1096. IopSetDeviceProblem(Device, DeviceProblemResourceConflict, Status);
  1097. goto ResourceAllocationWorkerEnd;
  1098. }
  1099. //
  1100. // Resources were successfully allocated. Advance the state and kick the
  1101. // device to start.
  1102. //
  1103. IopSetDeviceState(Device, DeviceResourcesAssigned);
  1104. Status = IopQueueDeviceWork(Device, DeviceActionStart, NULL, 0);
  1105. if (!KSUCCESS(Status)) {
  1106. IopSetDeviceProblem(Device, DeviceProblemFailedToQueueStart, Status);
  1107. }
  1108. ResourceAllocationWorkerEnd:
  1109. OldWorkItemCount = RtlAtomicAdd(&IoDeviceWorkItemsQueued, -1);
  1110. if (OldWorkItemCount == 1) {
  1111. IopQueueDelayedResourceAssignment();
  1112. }
  1113. return;
  1114. }
  1115. VOID
  1116. IopDelayedResourceAssignmentWorker (
  1117. PVOID Parameter
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. This routine attempts to assign resources for all devices whose resource
  1122. assignment was delayed to allow boot allocations to take priority.
  1123. Arguments:
  1124. Parameter - Supplies the work item parameter, which in this case is unused.
  1125. Return Value:
  1126. None.
  1127. --*/
  1128. {
  1129. UINTN DeviceCount;
  1130. UINTN DeviceIndex;
  1131. PDEVICE *Devices;
  1132. DeviceCount = IoDelayedDeviceCount;
  1133. Devices = IoDelayedDevices;
  1134. IoDelayedDevices = NULL;
  1135. IoDelayedDeviceCount = 0;
  1136. for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex += 1) {
  1137. IopResourceAllocationWorker(Devices[DeviceIndex]);
  1138. }
  1139. if (DeviceCount != 0) {
  1140. MmFreePagedPool(Devices);
  1141. }
  1142. return;
  1143. }
  1144. KSTATUS
  1145. IopCreateAndInitializeResourceRequirement (
  1146. PRESOURCE_REQUIREMENT RequirementTemplate,
  1147. PRESOURCE_REQUIREMENT *NewRequirement
  1148. )
  1149. /*++
  1150. Routine Description:
  1151. This routine creates a new resource requirement from the given template.
  1152. Arguments:
  1153. RequirementTemplate - Supplies a pointer to the resource requirement to use
  1154. as a template. The memory passed in will not actually be used, a copy of
  1155. the requirement will be created and initialized. A copy of the
  1156. additional data is also made.
  1157. NewRequirement - Supplies a pointer where the new resource requirement will
  1158. be returned upon success.
  1159. Return Value:
  1160. STATUS_SUCCESS on success.
  1161. STATUS_INVALID_PARAMETER if parameter validation failed.
  1162. STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
  1163. --*/
  1164. {
  1165. UINTN AllocationSize;
  1166. PRESOURCE_REQUIREMENT CreatedRequirement;
  1167. UINTN DataSize;
  1168. KSTATUS Status;
  1169. CreatedRequirement = NULL;
  1170. //
  1171. // Check parameters.
  1172. //
  1173. if ((RequirementTemplate->Minimum != 0) &&
  1174. ((RequirementTemplate->Minimum > RequirementTemplate->Maximum) ||
  1175. (RequirementTemplate->Minimum + RequirementTemplate->Length >
  1176. RequirementTemplate->Maximum) ||
  1177. (RequirementTemplate->Minimum + RequirementTemplate->Length <
  1178. RequirementTemplate->Minimum))) {
  1179. Status = STATUS_INVALID_PARAMETER;
  1180. goto CreateAndInitializeResourceRequirementEnd;
  1181. }
  1182. if ((RequirementTemplate->Type == ResourceTypeInvalid) ||
  1183. (RequirementTemplate->Type >= ResourceTypeCount)) {
  1184. Status = STATUS_INVALID_PARAMETER;
  1185. goto CreateAndInitializeResourceRequirementEnd;
  1186. }
  1187. DataSize = RequirementTemplate->DataSize;
  1188. if (DataSize > RESOURCE_MAX_ADDITIONAL_DATA) {
  1189. Status = STATUS_INVALID_PARAMETER;
  1190. goto CreateAndInitializeResourceRequirementEnd;
  1191. }
  1192. AllocationSize = sizeof(RESOURCE_REQUIREMENT) + DataSize;
  1193. //
  1194. // Create the new requirement.
  1195. //
  1196. CreatedRequirement = MmAllocatePagedPool(AllocationSize,
  1197. RESOURCE_ALLOCATION_TAG);
  1198. if (CreatedRequirement == NULL) {
  1199. Status = STATUS_INSUFFICIENT_RESOURCES;
  1200. goto CreateAndInitializeResourceRequirementEnd;
  1201. }
  1202. RtlZeroMemory(CreatedRequirement, sizeof(RESOURCE_REQUIREMENT));
  1203. INITIALIZE_LIST_HEAD(&(CreatedRequirement->AlternativeListEntry));
  1204. CreatedRequirement->Type = RequirementTemplate->Type;
  1205. CreatedRequirement->Minimum = RequirementTemplate->Minimum;
  1206. CreatedRequirement->Maximum = RequirementTemplate->Maximum;
  1207. CreatedRequirement->Alignment = RequirementTemplate->Alignment;
  1208. if (CreatedRequirement->Alignment == 0) {
  1209. CreatedRequirement->Alignment = 1;
  1210. }
  1211. CreatedRequirement->Length = RequirementTemplate->Length;
  1212. CreatedRequirement->Characteristics = RequirementTemplate->Characteristics;
  1213. CreatedRequirement->Flags = RequirementTemplate->Flags;
  1214. CreatedRequirement->OwningRequirement =
  1215. RequirementTemplate->OwningRequirement;
  1216. CreatedRequirement->Provider = RequirementTemplate->Provider;
  1217. if (DataSize != 0) {
  1218. CreatedRequirement->Data = CreatedRequirement + 1;
  1219. RtlCopyMemory(CreatedRequirement->Data,
  1220. RequirementTemplate->Data,
  1221. DataSize);
  1222. CreatedRequirement->DataSize = DataSize;
  1223. }
  1224. Status = STATUS_SUCCESS;
  1225. CreateAndInitializeResourceRequirementEnd:
  1226. if (!KSUCCESS(Status)) {
  1227. if (CreatedRequirement != NULL) {
  1228. MmFreePagedPool(CreatedRequirement);
  1229. CreatedRequirement = NULL;
  1230. }
  1231. }
  1232. *NewRequirement = CreatedRequirement;
  1233. return Status;
  1234. }
  1235. PSTR
  1236. IopGetResourceTypeString (
  1237. RESOURCE_TYPE Type
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. This routine returns a string representing the given resource type.
  1242. Arguments:
  1243. Type - Supplies the resource type.
  1244. Return Value:
  1245. Returns a pointer to a constant read-only string representing the given
  1246. resource type.
  1247. --*/
  1248. {
  1249. PSTR ResourceType;
  1250. switch (Type) {
  1251. case ResourceTypeInvalid:
  1252. ResourceType = "Invalid";
  1253. break;
  1254. case ResourceTypePhysicalAddressSpace:
  1255. ResourceType = "Physical Address";
  1256. break;
  1257. case ResourceTypeIoPort:
  1258. ResourceType = "I/O Port";
  1259. break;
  1260. case ResourceTypeInterruptLine:
  1261. ResourceType = "Interrupt Line";
  1262. break;
  1263. case ResourceTypeInterruptVector:
  1264. ResourceType = "Interrupt Vector";
  1265. break;
  1266. case ResourceTypeBusNumber:
  1267. ResourceType = "Bus Number";
  1268. break;
  1269. case ResourceTypeDmaChannel:
  1270. ResourceType = "DMA Channel";
  1271. break;
  1272. case ResourceTypeVendorSpecific:
  1273. ResourceType = "Vendor Specific";
  1274. break;
  1275. case ResourceTypeGpio:
  1276. ResourceType = "GPIO";
  1277. break;
  1278. case ResourceTypeSimpleBus:
  1279. ResourceType = "SPB";
  1280. break;
  1281. default:
  1282. ResourceType = "INVALID RESOURCE TYPE";
  1283. break;
  1284. }
  1285. return ResourceType;
  1286. }