123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- devres.c
- Abstract:
- This module implements device resource requirement and allocation
- functionality.
- Author:
- Evan Green 2-Dec-2012
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/kernel.h>
- #include "iop.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // Some resources need to be non-paged because they may be used by the paging
- // device during I/O transfers.
- //
- #define RESOURCE_TYPE_NON_PAGED(_ResourceType) \
- ((_ResourceType) == ResourceTypeDmaChannel)
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define RESOURCE_ALLOCATION_TAG 0x4C736552 // 'LseR'
- //
- // Set a sane limit on how big these allocations can get.
- //
- #define RESOURCE_MAX_ADDITIONAL_DATA 0x1000
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- VOID
- IopResourceAllocationWorker (
- PVOID Parameter
- );
- VOID
- IopDelayedResourceAssignmentWorker (
- PVOID Parameter
- );
- KSTATUS
- IopCreateAndInitializeResourceRequirement (
- PRESOURCE_REQUIREMENT RequirementTemplate,
- PRESOURCE_REQUIREMENT *NewRequirement
- );
- PSTR
- IopGetResourceTypeString (
- RESOURCE_TYPE Type
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Store the array of devices that were delayed until the initial enumeration
- // was complete.
- //
- PDEVICE *IoDelayedDevices;
- UINTN IoDelayedDeviceCount;
- //
- // ------------------------------------------------------------------ Functions
- //
- //
- // Resource requirement list support routines.
- //
- KERNEL_API
- PRESOURCE_REQUIREMENT_LIST
- IoCreateResourceRequirementList (
- VOID
- )
- /*++
- Routine Description:
- This routine creates a new empty resource requirement list.
- Arguments:
- None.
- Return Value:
- Returns a pointer to the new resource requirement list on success.
- NULL on allocation failure.
- --*/
- {
- PRESOURCE_REQUIREMENT_LIST List;
- List = MmAllocatePagedPool(sizeof(RESOURCE_REQUIREMENT_LIST),
- RESOURCE_ALLOCATION_TAG);
- if (List == NULL) {
- return NULL;
- }
- RtlZeroMemory(List, sizeof(RESOURCE_REQUIREMENT_LIST));
- INITIALIZE_LIST_HEAD(&(List->RequirementListHead));
- return List;
- }
- KERNEL_API
- VOID
- IoDestroyResourceRequirementList (
- PRESOURCE_REQUIREMENT_LIST ResourceRequirementList
- )
- /*++
- Routine Description:
- This routine releases the memory associated with a resource requirement
- list, and any items on that list.
- Arguments:
- ResourceRequirementList - Supplies a pointer to the resource requirement
- list to destroy.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PRESOURCE_REQUIREMENT ResourceRequirement;
- while (LIST_EMPTY(&(ResourceRequirementList->RequirementListHead)) ==
- FALSE) {
- CurrentEntry = ResourceRequirementList->RequirementListHead.Next;
- ResourceRequirement = LIST_VALUE(CurrentEntry,
- RESOURCE_REQUIREMENT,
- ListEntry);
- IoRemoveResourceRequirement(ResourceRequirement);
- }
- if (ResourceRequirementList->ListEntry.Next != NULL) {
- LIST_REMOVE(&(ResourceRequirementList->ListEntry));
- }
- MmFreePagedPool(ResourceRequirementList);
- return;
- }
- KERNEL_API
- KSTATUS
- IoCreateAndAddResourceRequirement (
- PRESOURCE_REQUIREMENT Requirement,
- PRESOURCE_REQUIREMENT_LIST ResourceRequirementList,
- PRESOURCE_REQUIREMENT *NewRequirement
- )
- /*++
- Routine Description:
- This routine creates a new resource requirement from the given template and
- inserts it into the given resource requirement list.
- Arguments:
- Requirement - Supplies a pointer to the resource requirement to use as a
- template. The memory passed in will not actually be used, a copy of the
- requirement will be created, initialized, and placed on the list.
- ResourceRequirementList - Supplies a pointer to the resource requirement
- list to add the requirement to.
- NewRequirement - Supplies an optional pointer to the resource requirement
- that was created. The system owns this memory, the caller should not
- attempt to free it directly.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INVALID_PARAMETER if parameter validation failed.
- STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
- --*/
- {
- PRESOURCE_REQUIREMENT CreatedRequirement;
- KSTATUS Status;
- CreatedRequirement = NULL;
- Status = IopCreateAndInitializeResourceRequirement(Requirement,
- &CreatedRequirement);
- if (!KSUCCESS(Status)) {
- goto CreateAndAddResourceRequirementEnd;
- }
- //
- // Add the requirement to the end of the list.
- //
- INSERT_BEFORE(&(CreatedRequirement->ListEntry),
- &(ResourceRequirementList->RequirementListHead));
- Status = STATUS_SUCCESS;
- CreateAndAddResourceRequirementEnd:
- if (NewRequirement != NULL) {
- *NewRequirement = CreatedRequirement;
- }
- return Status;
- }
- KERNEL_API
- VOID
- IoRemoveResourceRequirement (
- PRESOURCE_REQUIREMENT Requirement
- )
- /*++
- Routine Description:
- This routine removes the given resource descriptor from its resource list
- and frees the memory associated with that descriptor.
- Arguments:
- Requirement - Supplies a pointer to the resource requirement to remove and
- destroy.
- Return Value:
- None.
- --*/
- {
- PRESOURCE_REQUIREMENT Alternative;
- PLIST_ENTRY CurrentEntry;
- //
- // Loop through and destroy all alternatives to this resource requirement.
- //
- CurrentEntry = Requirement->AlternativeListEntry.Next;
- while (CurrentEntry != &(Requirement->AlternativeListEntry)) {
- Alternative = LIST_VALUE(CurrentEntry,
- RESOURCE_REQUIREMENT,
- AlternativeListEntry);
- //
- // It's important to move the list entry before the alternative is
- // destroyed!
- //
- CurrentEntry = CurrentEntry->Next;
- IoRemoveResourceRequirementAlternative(Alternative);
- }
- ASSERT(LIST_EMPTY(&(Requirement->AlternativeListEntry)) != FALSE);
- LIST_REMOVE(&(Requirement->ListEntry));
- MmFreePagedPool(Requirement);
- return;
- }
- KERNEL_API
- KSTATUS
- IoCreateAndAddResourceRequirementAlternative (
- PRESOURCE_REQUIREMENT Alternative,
- PRESOURCE_REQUIREMENT Requirement
- )
- /*++
- Routine Description:
- This routine creates a new resource requirement alternative from the given
- template and inserts it into the given resource requirement alternative
- list.
- Arguments:
- Alternative - Supplies a pointer to the resource requirement to use as a
- template. The memory passed in will not actually be used, a copy of the
- requirement will be created, initialized, and placed on the list.
- Requirement - Supplies a pointer to the resource requirement to add the
- alternative to.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INVALID_PARAMETER if parameter validation failed.
- STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
- --*/
- {
- PRESOURCE_REQUIREMENT NewRequirement;
- KSTATUS Status;
- Status = IopCreateAndInitializeResourceRequirement(Alternative,
- &NewRequirement);
- if (!KSUCCESS(Status)) {
- goto CreateAndAddResourceRequirementAlternativeEnd;
- }
- //
- // Add the alternative to the end of the list.
- //
- INSERT_BEFORE(&(NewRequirement->AlternativeListEntry),
- &(Requirement->AlternativeListEntry));
- Status = STATUS_SUCCESS;
- CreateAndAddResourceRequirementAlternativeEnd:
- return Status;
- }
- KERNEL_API
- VOID
- IoRemoveResourceRequirementAlternative (
- PRESOURCE_REQUIREMENT Alternative
- )
- /*++
- Routine Description:
- This routine removes the given resource requirement alternative from its
- resource list and frees the memory associated with that descriptor.
- Arguments:
- Alternative - Supplies a pointer to the resource requirement alternative
- to remove and destroy.
- Return Value:
- None.
- --*/
- {
- //
- // This had better be an alternative and not a first requirement.
- //
- ASSERT(Alternative->ListEntry.Next == NULL);
- LIST_REMOVE(&(Alternative->AlternativeListEntry));
- MmFreePagedPool(Alternative);
- return;
- }
- KERNEL_API
- KSTATUS
- IoCreateAndAddInterruptVectorsForLines (
- PRESOURCE_CONFIGURATION_LIST ConfigurationList,
- PRESOURCE_REQUIREMENT VectorTemplate
- )
- /*++
- Routine Description:
- This routine creates a new vector resource requirement for each interrupt
- line requirement in the given configuration list.
- Arguments:
- ConfigurationList - Supplies a pointer to the resource configuration list
- to iterate through.
- VectorTemplate - Supplies a pointer to a template to use when creating the
- vector resource requirements.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INVALID_PARAMETER if parameter validation failed.
- STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
- --*/
- {
- ULONGLONG LineCharacteristics;
- PRESOURCE_REQUIREMENT NextRequirement;
- PRESOURCE_REQUIREMENT Requirement;
- PRESOURCE_REQUIREMENT_LIST RequirementList;
- KSTATUS Status;
- ULONGLONG VectorCharacteristics;
- //
- // Loop through all configuration lists.
- //
- if (ConfigurationList == NULL) {
- Status = STATUS_SUCCESS;
- goto CreateAndAddInterruptVectorsForLinesEnd;
- }
- RequirementList = IoGetNextResourceConfiguration(ConfigurationList, NULL);
- while (RequirementList != NULL) {
- //
- // Loop through every requirement in the list.
- //
- Requirement = IoGetNextResourceRequirement(RequirementList, NULL);
- while (Requirement != NULL) {
- //
- // Get the next resource requirement.
- //
- NextRequirement = IoGetNextResourceRequirement(RequirementList,
- Requirement);
- //
- // Skip the requirement if it is not an interrupt line.
- //
- if (Requirement->Type != ResourceTypeInterruptLine) {
- Requirement = NextRequirement;
- continue;
- }
- //
- // The requirement is an interrupt line. Add a vector requirement
- // based on the template.
- //
- VectorCharacteristics = 0;
- LineCharacteristics = Requirement->Characteristics;
- if ((LineCharacteristics & INTERRUPT_LINE_ACTIVE_LOW) != 0) {
- VectorCharacteristics |= INTERRUPT_VECTOR_ACTIVE_LOW;
- }
- if ((LineCharacteristics & INTERRUPT_LINE_ACTIVE_HIGH) != 0) {
- VectorCharacteristics |= INTERRUPT_VECTOR_ACTIVE_HIGH;
- }
- if ((LineCharacteristics & INTERRUPT_LINE_EDGE_TRIGGERED) != 0) {
- VectorCharacteristics |= INTERRUPT_VECTOR_EDGE_TRIGGERED;
- }
- //
- // Secondary interrupt lines have run-levels that may not
- // correspond in a direct way to their interrupt vector. These
- // types of vectors cannot be shared as it might create a conflict
- // of different run-levels for the same vector.
- //
- if ((LineCharacteristics & INTERRUPT_LINE_SECONDARY) != 0) {
- VectorTemplate->Flags |= RESOURCE_FLAG_NOT_SHAREABLE;
- }
- VectorTemplate->Characteristics = VectorCharacteristics;
- VectorTemplate->OwningRequirement = Requirement;
- Status = IoCreateAndAddResourceRequirement(VectorTemplate,
- RequirementList,
- NULL);
- if (!KSUCCESS(Status)) {
- goto CreateAndAddInterruptVectorsForLinesEnd;
- }
- Requirement = NextRequirement;
- }
- //
- // Get the next possible resource configuration.
- //
- RequirementList = IoGetNextResourceConfiguration(ConfigurationList,
- RequirementList);
- }
- Status = STATUS_SUCCESS;
- CreateAndAddInterruptVectorsForLinesEnd:
- return Status;
- }
- KERNEL_API
- PRESOURCE_REQUIREMENT
- IoGetNextResourceRequirement (
- PRESOURCE_REQUIREMENT_LIST ResourceRequirementList,
- PRESOURCE_REQUIREMENT CurrentEntry
- )
- /*++
- Routine Description:
- This routine returns a pointer to the next resource requirment in the
- resource requirement list.
- Arguments:
- ResourceRequirementList - Supplies a pointer to the resource requirement
- list to iterate through.
- CurrentEntry - Supplies an optional pointer to the previous resource
- requirement. If supplied, the function will return the resource
- requirement immediately after this one in the list. If NULL is
- supplied, this routine will return the first resource requirement in the
- list.
- Return Value:
- Returns a pointer to the next resource requirement in the given list on
- success, or NULL if the last resource requirement was reached.
- --*/
- {
- PLIST_ENTRY NextEntry;
- if (CurrentEntry != NULL) {
- NextEntry = CurrentEntry->ListEntry.Next;
- } else {
- NextEntry = ResourceRequirementList->RequirementListHead.Next;
- }
- if (NextEntry == &(ResourceRequirementList->RequirementListHead)) {
- return NULL;
- }
- return LIST_VALUE(NextEntry, RESOURCE_REQUIREMENT, ListEntry);
- }
- KERNEL_API
- PRESOURCE_REQUIREMENT
- IoGetNextResourceRequirementAlternative (
- PRESOURCE_REQUIREMENT ResourceRequirement,
- PRESOURCE_REQUIREMENT CurrentEntry
- )
- /*++
- Routine Description:
- This routine returns a pointer to the next resource requirment alternative
- in the alternative list for the requirement.
- Arguments:
- ResourceRequirement - Supplies a pointer to the resource requirement at
- the head of the list.
- CurrentEntry - Supplies an optional pointer to the current requirement
- alternative.
- Return Value:
- Returns a pointer to the next resource requirement alternative in the list
- on success, or NULL if the last resource requirement alternative was
- reached.
- --*/
- {
- PLIST_ENTRY NextEntry;
- if (CurrentEntry != NULL) {
- NextEntry = CurrentEntry->AlternativeListEntry.Next;
- } else {
- NextEntry = ResourceRequirement->AlternativeListEntry.Next;
- }
- if (NextEntry == &(ResourceRequirement->AlternativeListEntry)) {
- return NULL;
- }
- return LIST_VALUE(NextEntry, RESOURCE_REQUIREMENT, AlternativeListEntry);
- }
- //
- // Resource configuration list routines.
- //
- KERNEL_API
- PRESOURCE_CONFIGURATION_LIST
- IoCreateResourceConfigurationList (
- PRESOURCE_REQUIREMENT_LIST FirstConfiguration
- )
- /*++
- Routine Description:
- This routine creates a new resource configuration list. A resource
- configuration list is a collection of resource requirement lists, arranged
- from most desirable to least desirable. The system attempts selects the
- most desirable resource configuration that can be afforded.
- Arguments:
- FirstConfiguration - Supplies an optional pointer to the first configuration
- to put on the list. If NULL is supplied, an empty resource
- configuration list will be created.
- Return Value:
- Returns a pointer to the new resource configuration list on success.
- NULL on allocation failure.
- --*/
- {
- PRESOURCE_CONFIGURATION_LIST List;
- List = MmAllocatePagedPool(sizeof(RESOURCE_CONFIGURATION_LIST),
- RESOURCE_ALLOCATION_TAG);
- if (List == NULL) {
- return NULL;
- }
- RtlZeroMemory(List, sizeof(RESOURCE_CONFIGURATION_LIST));
- INITIALIZE_LIST_HEAD(&(List->RequirementListListHead));
- if (FirstConfiguration != NULL) {
- INSERT_AFTER(&(FirstConfiguration->ListEntry),
- &(List->RequirementListListHead));
- }
- return List;
- }
- KERNEL_API
- VOID
- IoDestroyResourceConfigurationList (
- PRESOURCE_CONFIGURATION_LIST ResourceConfigurationList
- )
- /*++
- Routine Description:
- This routine releases the memory associated with a resource configuration
- list, and any resource requirement lists it may contain.
- Arguments:
- ResourceConfigurationList - Supplies a pointer to the resource configuration
- list to destroy.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PRESOURCE_REQUIREMENT_LIST RequirementList;
- while (LIST_EMPTY(&(ResourceConfigurationList->RequirementListListHead)) ==
- FALSE) {
- CurrentEntry = ResourceConfigurationList->RequirementListListHead.Next;
- RequirementList = LIST_VALUE(CurrentEntry,
- RESOURCE_REQUIREMENT_LIST,
- ListEntry);
- IoDestroyResourceRequirementList(RequirementList);
- }
- MmFreePagedPool(ResourceConfigurationList);
- return;
- }
- KERNEL_API
- KSTATUS
- IoAddResourceConfiguration (
- PRESOURCE_REQUIREMENT_LIST Configuration,
- PRESOURCE_REQUIREMENT_LIST ConfigurationToInsertAfter,
- PRESOURCE_CONFIGURATION_LIST ConfigurationList
- )
- /*++
- Routine Description:
- This routine inserts an initialized resource configuration into a
- configuration list.
- Arguments:
- Configuration - Supplies a pointer to the resource configuration to insert
- into the list.
- ConfigurationToInsertAfter - Supplies an optional pointer indicating the
- location in the list to insert the configuration. If this pointer is
- supplied, the configuration will be inserted immediate after this
- parameter in the list. If NULL is supplied, the configuration will be
- added to the end of the list.
- ConfigurationList - Supplies a pointer to the list to add the configuration
- to.
- Return Value:
- Status code.
- --*/
- {
- ASSERT(Configuration->ListEntry.Next == NULL);
- if (ConfigurationToInsertAfter != NULL) {
- INSERT_AFTER(&(Configuration->ListEntry),
- &(ConfigurationToInsertAfter->ListEntry));
- } else {
- INSERT_BEFORE(&(Configuration->ListEntry),
- &(ConfigurationList->RequirementListListHead));
- }
- return STATUS_SUCCESS;
- }
- KERNEL_API
- VOID
- IoRemoveResourceConfiguration (
- PRESOURCE_REQUIREMENT_LIST Configuration,
- PRESOURCE_CONFIGURATION_LIST ConfigurationList
- )
- /*++
- Routine Description:
- This routine removes the given resource descriptor from its resource list.
- It does not free the memory associated with the configuration.
- Arguments:
- Configuration - Supplies a pointer to the configuration to remove.
- ConfigurationList - Supplies a pointer to the configuration list to remove
- the configuration from.
- Return Value:
- None.
- --*/
- {
- ASSERT(Configuration->ListEntry.Next != NULL);
- LIST_REMOVE(&(Configuration->ListEntry));
- Configuration->ListEntry.Next = NULL;
- return;
- }
- KERNEL_API
- PRESOURCE_REQUIREMENT_LIST
- IoGetNextResourceConfiguration (
- PRESOURCE_CONFIGURATION_LIST ConfigurationList,
- PRESOURCE_REQUIREMENT_LIST CurrentEntry
- )
- /*++
- Routine Description:
- This routine returns a pointer to the next resource configuration in the
- resource configuration list.
- Arguments:
- ConfigurationList - Supplies a pointer to the resource configuration list
- to iterate through.
- CurrentEntry - Supplies an optional pointer to the previous resource
- requirement list. If supplied, the function will return the
- configuration immediately after this one in the list. If NULL is
- supplied, this routine will return the first configuration in the
- list.
- Return Value:
- Returns a pointer to the next resource configuration in the given list on
- success, or NULL if the last resource requirement was reached.
- --*/
- {
- PLIST_ENTRY NextEntry;
- if (CurrentEntry != NULL) {
- NextEntry = CurrentEntry->ListEntry.Next;
- } else {
- NextEntry = ConfigurationList->RequirementListListHead.Next;
- }
- if (NextEntry == &(ConfigurationList->RequirementListListHead)) {
- return NULL;
- }
- return LIST_VALUE(NextEntry, RESOURCE_REQUIREMENT_LIST, ListEntry);
- }
- //
- // Resource allocation list support routines.
- //
- KERNEL_API
- PRESOURCE_ALLOCATION_LIST
- IoCreateResourceAllocationList (
- VOID
- )
- /*++
- Routine Description:
- This routine creates a new empty resource allocation list.
- Arguments:
- None.
- Return Value:
- Returns a pointer to the new resource allocation list on success.
- NULL on allocation failure.
- --*/
- {
- PRESOURCE_ALLOCATION_LIST List;
- List = MmAllocatePagedPool(sizeof(PRESOURCE_ALLOCATION_LIST),
- RESOURCE_ALLOCATION_TAG);
- if (List == NULL) {
- return NULL;
- }
- RtlZeroMemory(List, sizeof(PRESOURCE_ALLOCATION_LIST));
- INITIALIZE_LIST_HEAD(&(List->AllocationListHead));
- return List;
- }
- KERNEL_API
- VOID
- IoDestroyResourceAllocationList (
- PRESOURCE_ALLOCATION_LIST ResourceAllocationList
- )
- /*++
- Routine Description:
- This routine releases the memory associated with a resource allocation
- list, and any items on that list.
- Arguments:
- ResourceAllocationList - Supplies a pointer to the resource allocation
- list to destroy.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PRESOURCE_ALLOCATION ResourceAllocation;
- while (LIST_EMPTY(&(ResourceAllocationList->AllocationListHead)) ==
- FALSE) {
- CurrentEntry = ResourceAllocationList->AllocationListHead.Next;
- ResourceAllocation = LIST_VALUE(CurrentEntry,
- RESOURCE_ALLOCATION,
- ListEntry);
- IoRemoveResourceAllocation(ResourceAllocation, ResourceAllocationList);
- }
- MmFreePagedPool(ResourceAllocationList);
- return;
- }
- KERNEL_API
- KSTATUS
- IoCreateAndAddResourceAllocation (
- PRESOURCE_ALLOCATION Allocation,
- PRESOURCE_ALLOCATION_LIST ResourceAllocationList
- )
- /*++
- Routine Description:
- This routine creates a new resource allocation from the given template and
- inserts it into the given resource allocation list.
- Arguments:
- Allocation - Supplies a pointer to the resource allocation to use as a
- template. The memory passed in will not actually be used, a copy of the
- allocation will be created, initialized, and placed on the list.
- ResourceAllocationList - Supplies a pointer to the resource allocation
- list to add the allocation to.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INVALID_PARAMETER if parameter validation failed.
- STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
- --*/
- {
- UINTN AllocationSize;
- UINTN DataSize;
- PRESOURCE_ALLOCATION NewAllocation;
- KSTATUS Status;
- //
- // Check parameters.
- //
- if ((Allocation->Type == ResourceTypeInvalid) ||
- (Allocation->Type >= ResourceTypeCount)) {
- Status = STATUS_INVALID_PARAMETER;
- goto CreateAndAddResourceAllocationEnd;
- }
- DataSize = Allocation->DataSize;
- if (DataSize > RESOURCE_MAX_ADDITIONAL_DATA) {
- Status = STATUS_INVALID_PARAMETER;
- goto CreateAndAddResourceAllocationEnd;
- }
- //
- // Create the new resource allocation.
- //
- AllocationSize = sizeof(RESOURCE_ALLOCATION) + DataSize;
- if (RESOURCE_TYPE_NON_PAGED(Allocation->Type)) {
- NewAllocation = MmAllocateNonPagedPool(AllocationSize,
- RESOURCE_ALLOCATION_TAG);
- } else {
- NewAllocation = MmAllocatePagedPool(AllocationSize,
- RESOURCE_ALLOCATION_TAG);
- }
- if (NewAllocation == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto CreateAndAddResourceAllocationEnd;
- }
- RtlZeroMemory(NewAllocation, sizeof(RESOURCE_ALLOCATION));
- NewAllocation->Type = Allocation->Type;
- NewAllocation->Allocation = Allocation->Allocation;
- NewAllocation->Length = Allocation->Length;
- NewAllocation->Characteristics = Allocation->Characteristics;
- NewAllocation->Flags = Allocation->Flags;
- NewAllocation->OwningAllocation = Allocation->OwningAllocation;
- NewAllocation->Provider = Allocation->Provider;
- if (DataSize != 0) {
- NewAllocation->Data = NewAllocation + 1;
- NewAllocation->DataSize = DataSize;
- RtlCopyMemory(NewAllocation->Data, Allocation->Data, DataSize);
- }
- //
- // Add the allocation to the end of the list.
- //
- INSERT_BEFORE(&(NewAllocation->ListEntry),
- &(ResourceAllocationList->AllocationListHead));
- Status = STATUS_SUCCESS;
- CreateAndAddResourceAllocationEnd:
- return Status;
- }
- KERNEL_API
- VOID
- IoRemoveResourceAllocation (
- PRESOURCE_ALLOCATION Allocation,
- PRESOURCE_ALLOCATION_LIST ResourceAllocationList
- )
- /*++
- Routine Description:
- This routine removes the given resource descriptor from its resource list
- and frees the memory associated with that descriptor.
- Arguments:
- Allocation - Supplies a pointer to the allocation to remove.
- ResourceAllocationList - Supplies a pointer to the list to remove the
- allocation from.
- Return Value:
- None.
- --*/
- {
- ASSERT(ResourceAllocationList != NULL);
- LIST_REMOVE(&(Allocation->ListEntry));
- if (RESOURCE_TYPE_NON_PAGED(Allocation->Type)) {
- MmFreeNonPagedPool(Allocation);
- } else {
- MmFreePagedPool(Allocation);
- }
- return;
- }
- KERNEL_API
- PRESOURCE_ALLOCATION
- IoGetNextResourceAllocation (
- PRESOURCE_ALLOCATION_LIST ResourceAllocationList,
- PRESOURCE_ALLOCATION CurrentEntry
- )
- /*++
- Routine Description:
- This routine returns a pointer to the next resource allocation in the
- resource allocation list.
- Arguments:
- ResourceAllocationList - Supplies a pointer to the resource allocation
- list to iterate through.
- CurrentEntry - Supplies an optional pointer to the previous resource
- allocation. If supplied, the function will return the resource
- allocation immediately after this one in the list. If NULL is
- supplied, this routine will return the first resource allocation in the
- list.
- Return Value:
- Returns a pointer to the next resource allocation in the given list on
- success, or NULL if the last resource allocation was reached.
- --*/
- {
- PLIST_ENTRY NextEntry;
- if (ResourceAllocationList == NULL) {
- return NULL;
- }
- if (CurrentEntry != NULL) {
- NextEntry = CurrentEntry->ListEntry.Next;
- } else {
- NextEntry = ResourceAllocationList->AllocationListHead.Next;
- }
- if (NextEntry == &(ResourceAllocationList->AllocationListHead)) {
- return NULL;
- }
- return LIST_VALUE(NextEntry, RESOURCE_ALLOCATION, ListEntry);
- }
- KERNEL_API
- VOID
- IoDebugPrintResourceConfigurationList (
- PRESOURCE_CONFIGURATION_LIST ConfigurationList
- )
- /*++
- Routine Description:
- This routine prints a resource configuration list out to the debugger.
- Arguments:
- ConfigurationList - Supplies a pointer to the resource configuration list to
- print.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PRESOURCE_REQUIREMENT_LIST RequirementList;
- RtlDebugPrint("Resource Configuration List at %x:\n", ConfigurationList);
- CurrentEntry = ConfigurationList->RequirementListListHead.Next;
- while (CurrentEntry != &(ConfigurationList->RequirementListListHead)) {
- RequirementList = LIST_VALUE(CurrentEntry,
- RESOURCE_REQUIREMENT_LIST,
- ListEntry);
- CurrentEntry = CurrentEntry->Next;
- IoDebugPrintResourceRequirementList(1, RequirementList);
- }
- return;
- }
- KERNEL_API
- VOID
- IoDebugPrintResourceRequirementList (
- ULONG IndentationLevel,
- PRESOURCE_REQUIREMENT_LIST RequirementList
- )
- /*++
- Routine Description:
- This routine prints a resource requirement list out to the debugger.
- Arguments:
- IndentationLevel - Supplies the indentation level to print this list
- at. Supply 0 if this function is called directly.
- RequirementList - Supplies a pointer to the resource requirement list to
- print.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- ULONG IndentationIndex;
- PRESOURCE_REQUIREMENT Requirement;
- for (IndentationIndex = 0;
- IndentationIndex < IndentationLevel;
- IndentationIndex += 1) {
- RtlDebugPrint(" ");
- }
- RtlDebugPrint("Resource Requirement List at %x:\n", RequirementList);
- CurrentEntry = RequirementList->RequirementListHead.Next;
- while (CurrentEntry != &(RequirementList->RequirementListHead)) {
- Requirement = LIST_VALUE(CurrentEntry, RESOURCE_REQUIREMENT, ListEntry);
- CurrentEntry = CurrentEntry->Next;
- IoDebugPrintResourceRequirement(IndentationLevel + 1, Requirement);
- }
- return;
- }
- KERNEL_API
- VOID
- IoDebugPrintResourceRequirement (
- ULONG IndentationLevel,
- PRESOURCE_REQUIREMENT Requirement
- )
- /*++
- Routine Description:
- This routine prints a resource requirement out to the debugger.
- Arguments:
- IndentationLevel - Supplies the indentation level to print this requirement
- at. Supply 0 if this function is called directly.
- Requirement - Supplies a pointer to the resource requirement to print.
- Return Value:
- None.
- --*/
- {
- PRESOURCE_REQUIREMENT Alternative;
- PLIST_ENTRY CurrentEntry;
- ULONG IndentationIndex;
- PSTR ResourceType;
- for (IndentationIndex = 0;
- IndentationIndex < IndentationLevel;
- IndentationIndex += 1) {
- RtlDebugPrint(" ");
- }
- //
- // Get the resource type.
- //
- ResourceType = IopGetResourceTypeString(Requirement->Type);
- RtlDebugPrint("%x %16s: From %08I64x to %08I64x, Len %I64x, Align %08I64x, "
- "Char: %I64x, Flags: %I64x, Owner: %08x\n",
- Requirement,
- ResourceType,
- Requirement->Minimum,
- Requirement->Maximum,
- Requirement->Length,
- Requirement->Alignment,
- Requirement->Characteristics,
- Requirement->Flags,
- Requirement->OwningRequirement);
- //
- // If the requirement is not attached to a resource requirement list,
- // don't try to traverse alternatives.
- //
- if (Requirement->ListEntry.Next == NULL) {
- return;
- }
- //
- // Loop through and recursively print out all alternatives.
- //
- CurrentEntry = Requirement->AlternativeListEntry.Next;
- while (CurrentEntry != &(Requirement->AlternativeListEntry)) {
- Alternative = LIST_VALUE(CurrentEntry,
- RESOURCE_REQUIREMENT,
- AlternativeListEntry);
- CurrentEntry = CurrentEntry->Next;
- IoDebugPrintResourceRequirement(IndentationLevel + 1, Alternative);
- }
- return;
- }
- KERNEL_API
- VOID
- IoDebugPrintResourceAllocationList (
- ULONG IndentationLevel,
- PRESOURCE_ALLOCATION_LIST AllocationList
- )
- /*++
- Routine Description:
- This routine prints a resource allocation list out to the debugger.
- Arguments:
- IndentationLevel - Supplies the indentation level to print this list
- at. Supply 0 if this function is called directly.
- AllocationList - Supplies a pointer to the resource allocation list to
- print.
- Return Value:
- None.
- --*/
- {
- PRESOURCE_ALLOCATION Allocation;
- PLIST_ENTRY CurrentEntry;
- ULONG IndentationIndex;
- for (IndentationIndex = 0;
- IndentationIndex < IndentationLevel;
- IndentationIndex += 1) {
- RtlDebugPrint(" ");
- }
- RtlDebugPrint("Resource Allocation List at %x:\n", AllocationList);
- CurrentEntry = AllocationList->AllocationListHead.Next;
- while (CurrentEntry != &(AllocationList->AllocationListHead)) {
- Allocation = LIST_VALUE(CurrentEntry, RESOURCE_ALLOCATION, ListEntry);
- CurrentEntry = CurrentEntry->Next;
- IoDebugPrintResourceAllocation(IndentationLevel + 1, Allocation);
- }
- return;
- }
- KERNEL_API
- VOID
- IoDebugPrintResourceAllocation (
- ULONG IndentationLevel,
- PRESOURCE_ALLOCATION Allocation
- )
- /*++
- Routine Description:
- This routine prints a resource allocation out to the debugger.
- Arguments:
- IndentationLevel - Supplies the indentation level to print this allocation
- at. Supply 0 if this function is called directly.
- Allocation - Supplies a pointer to the resource allocation to print.
- Return Value:
- None.
- --*/
- {
- ULONG IndentationIndex;
- PSTR ResourceType;
- for (IndentationIndex = 0;
- IndentationIndex < IndentationLevel;
- IndentationIndex += 1) {
- RtlDebugPrint(" ");
- }
- ResourceType = IopGetResourceTypeString(Allocation->Type);
- RtlDebugPrint("%08x %16s: %08I64x, Len %08I64x, Char %I64x, Flags %I64x "
- "Owner %08x ",
- Allocation,
- ResourceType,
- Allocation->Allocation,
- Allocation->Length,
- Allocation->Characteristics,
- Allocation->Flags,
- Allocation->OwningAllocation);
- if ((Allocation->Flags & RESOURCE_FLAG_NOT_SHAREABLE) != 0) {
- RtlDebugPrint("NotShared ");
- }
- RtlDebugPrint("\n");
- return;
- }
- KSTATUS
- IopQueueResourceAssignment (
- PDEVICE Device
- )
- /*++
- Routine Description:
- This routine puts this device in the resource assignment queue.
- Arguments:
- Device - Supplies a pointer to the device to queue for resource assignment.
- Return Value:
- Status code indicating whether or not the device was successfully queued.
- (Not that it successfully made it through the queue or was processed in
- any way).
- --*/
- {
- DEVICE_STATE OldState;
- KSTATUS Status;
- //
- // If the device has no resource requirements and no boot resources, move
- // the device straight to resources assigned.
- //
- if ((Device->ResourceRequirements == NULL) &&
- (Device->BootResources == NULL)) {
- Status = STATUS_SUCCESS;
- IopSetDeviceState(Device, DeviceResourcesAssigned);
- goto QueueResourceAssignmentEnd;
- }
- //
- // Set the state as if the operation was successful so that this routine is
- // not racing with the worker to set the state later.
- //
- OldState = Device->State;
- IopSetDeviceState(Device, DeviceResourceAssignmentQueued);
- RtlAtomicAdd(&IoDeviceWorkItemsQueued, 1);
- Status = KeCreateAndQueueWorkItem(IoResourceAllocationWorkQueue,
- WorkPriorityNormal,
- IopResourceAllocationWorker,
- Device);
- //
- // If it didn't work, set the state back to what it was before, resource
- // assignment work was not queued.
- //
- if (!KSUCCESS(Status)) {
- RtlAtomicAdd(&IoDeviceWorkItemsQueued, -1);
- IopSetDeviceState(Device, OldState);
- IopSetDeviceProblem(Device,
- DeviceProblemFailedToQueueResourceAssignmentWork,
- Status);
- }
- QueueResourceAssignmentEnd:
- return Status;
- }
- KSTATUS
- IopQueueDelayedResourceAssignment (
- VOID
- )
- /*++
- Routine Description:
- This routine queues resource assignment for devices that were delayed to
- allow devices with boot resources to go first.
- Arguments:
- None.
- Return Value:
- Status code.
- --*/
- {
- KSTATUS Status;
- Status = KeCreateAndQueueWorkItem(IoResourceAllocationWorkQueue,
- WorkPriorityNormal,
- IopDelayedResourceAssignmentWorker,
- NULL);
- return Status;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- IopResourceAllocationWorker (
- PVOID Parameter
- )
- /*++
- Routine Description:
- This routine is workhorse function fo the resource allocation work queue.
- It attempts to satisfy the resource requirements of a device.
- Arguments:
- Parameter - Supplies the work item parameter, which in this case is a
- pointer to the device to try and allocate resource for.
- Return Value:
- None. If the allocation is successful, the state in the device will be
- advanced and work will be queued to start the device. If the allocation
- fails, the device will be marked with a problem code.
- --*/
- {
- PDEVICE Device;
- UINTN OldWorkItemCount;
- KSTATUS Status;
- Device = (PDEVICE)Parameter;
- //
- // Attempt to satisfy the resource requirements of the device.
- //
- Status = IopProcessResourceRequirements(Device);
- if (!KSUCCESS(Status)) {
- IopSetDeviceProblem(Device, DeviceProblemResourceConflict, Status);
- goto ResourceAllocationWorkerEnd;
- }
- //
- // Resources were successfully allocated. Advance the state and kick the
- // device to start.
- //
- IopSetDeviceState(Device, DeviceResourcesAssigned);
- Status = IopQueueDeviceWork(Device, DeviceActionStart, NULL, 0);
- if (!KSUCCESS(Status)) {
- IopSetDeviceProblem(Device, DeviceProblemFailedToQueueStart, Status);
- }
- ResourceAllocationWorkerEnd:
- OldWorkItemCount = RtlAtomicAdd(&IoDeviceWorkItemsQueued, -1);
- if (OldWorkItemCount == 1) {
- IopQueueDelayedResourceAssignment();
- }
- return;
- }
- VOID
- IopDelayedResourceAssignmentWorker (
- PVOID Parameter
- )
- /*++
- Routine Description:
- This routine attempts to assign resources for all devices whose resource
- assignment was delayed to allow boot allocations to take priority.
- Arguments:
- Parameter - Supplies the work item parameter, which in this case is unused.
- Return Value:
- None.
- --*/
- {
- UINTN DeviceCount;
- UINTN DeviceIndex;
- PDEVICE *Devices;
- DeviceCount = IoDelayedDeviceCount;
- Devices = IoDelayedDevices;
- IoDelayedDevices = NULL;
- IoDelayedDeviceCount = 0;
- for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex += 1) {
- IopResourceAllocationWorker(Devices[DeviceIndex]);
- }
- if (DeviceCount != 0) {
- MmFreePagedPool(Devices);
- }
- return;
- }
- KSTATUS
- IopCreateAndInitializeResourceRequirement (
- PRESOURCE_REQUIREMENT RequirementTemplate,
- PRESOURCE_REQUIREMENT *NewRequirement
- )
- /*++
- Routine Description:
- This routine creates a new resource requirement from the given template.
- Arguments:
- RequirementTemplate - Supplies a pointer to the resource requirement to use
- as a template. The memory passed in will not actually be used, a copy of
- the requirement will be created and initialized. A copy of the
- additional data is also made.
- NewRequirement - Supplies a pointer where the new resource requirement will
- be returned upon success.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INVALID_PARAMETER if parameter validation failed.
- STATUS_INSUFFICIENT_RESOURCES if the required memory could not be allocated.
- --*/
- {
- UINTN AllocationSize;
- PRESOURCE_REQUIREMENT CreatedRequirement;
- UINTN DataSize;
- KSTATUS Status;
- CreatedRequirement = NULL;
- //
- // Check parameters.
- //
- if ((RequirementTemplate->Minimum != 0) &&
- ((RequirementTemplate->Minimum > RequirementTemplate->Maximum) ||
- (RequirementTemplate->Minimum + RequirementTemplate->Length >
- RequirementTemplate->Maximum) ||
- (RequirementTemplate->Minimum + RequirementTemplate->Length <
- RequirementTemplate->Minimum))) {
- Status = STATUS_INVALID_PARAMETER;
- goto CreateAndInitializeResourceRequirementEnd;
- }
- if ((RequirementTemplate->Type == ResourceTypeInvalid) ||
- (RequirementTemplate->Type >= ResourceTypeCount)) {
- Status = STATUS_INVALID_PARAMETER;
- goto CreateAndInitializeResourceRequirementEnd;
- }
- DataSize = RequirementTemplate->DataSize;
- if (DataSize > RESOURCE_MAX_ADDITIONAL_DATA) {
- Status = STATUS_INVALID_PARAMETER;
- goto CreateAndInitializeResourceRequirementEnd;
- }
- AllocationSize = sizeof(RESOURCE_REQUIREMENT) + DataSize;
- //
- // Create the new requirement.
- //
- CreatedRequirement = MmAllocatePagedPool(AllocationSize,
- RESOURCE_ALLOCATION_TAG);
- if (CreatedRequirement == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto CreateAndInitializeResourceRequirementEnd;
- }
- RtlZeroMemory(CreatedRequirement, sizeof(RESOURCE_REQUIREMENT));
- INITIALIZE_LIST_HEAD(&(CreatedRequirement->AlternativeListEntry));
- CreatedRequirement->Type = RequirementTemplate->Type;
- CreatedRequirement->Minimum = RequirementTemplate->Minimum;
- CreatedRequirement->Maximum = RequirementTemplate->Maximum;
- CreatedRequirement->Alignment = RequirementTemplate->Alignment;
- if (CreatedRequirement->Alignment == 0) {
- CreatedRequirement->Alignment = 1;
- }
- CreatedRequirement->Length = RequirementTemplate->Length;
- CreatedRequirement->Characteristics = RequirementTemplate->Characteristics;
- CreatedRequirement->Flags = RequirementTemplate->Flags;
- CreatedRequirement->OwningRequirement =
- RequirementTemplate->OwningRequirement;
- CreatedRequirement->Provider = RequirementTemplate->Provider;
- if (DataSize != 0) {
- CreatedRequirement->Data = CreatedRequirement + 1;
- RtlCopyMemory(CreatedRequirement->Data,
- RequirementTemplate->Data,
- DataSize);
- CreatedRequirement->DataSize = DataSize;
- }
- Status = STATUS_SUCCESS;
- CreateAndInitializeResourceRequirementEnd:
- if (!KSUCCESS(Status)) {
- if (CreatedRequirement != NULL) {
- MmFreePagedPool(CreatedRequirement);
- CreatedRequirement = NULL;
- }
- }
- *NewRequirement = CreatedRequirement;
- return Status;
- }
- PSTR
- IopGetResourceTypeString (
- RESOURCE_TYPE Type
- )
- /*++
- Routine Description:
- This routine returns a string representing the given resource type.
- Arguments:
- Type - Supplies the resource type.
- Return Value:
- Returns a pointer to a constant read-only string representing the given
- resource type.
- --*/
- {
- PSTR ResourceType;
- switch (Type) {
- case ResourceTypeInvalid:
- ResourceType = "Invalid";
- break;
- case ResourceTypePhysicalAddressSpace:
- ResourceType = "Physical Address";
- break;
- case ResourceTypeIoPort:
- ResourceType = "I/O Port";
- break;
- case ResourceTypeInterruptLine:
- ResourceType = "Interrupt Line";
- break;
- case ResourceTypeInterruptVector:
- ResourceType = "Interrupt Vector";
- break;
- case ResourceTypeBusNumber:
- ResourceType = "Bus Number";
- break;
- case ResourceTypeDmaChannel:
- ResourceType = "DMA Channel";
- break;
- case ResourceTypeVendorSpecific:
- ResourceType = "Vendor Specific";
- break;
- case ResourceTypeGpio:
- ResourceType = "GPIO";
- break;
- case ResourceTypeSimpleBus:
- ResourceType = "SPB";
- break;
- default:
- ResourceType = "INVALID RESOURCE TYPE";
- break;
- }
- return ResourceType;
- }
|