2 * COPYRIGHT: See COPYING in the top level directory
4 * FILE: drivers/wdm/audio/backpln/portcls/resource.cpp
5 * PURPOSE: Port Class driver / ResourceList implementation
6 * PROGRAMMER: Andrew Greenwood
12 #include "private.hpp"
14 class CResourceList
: public IResourceList
17 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
19 STDMETHODIMP_(ULONG
) AddRef()
21 InterlockedIncrement(&m_Ref
);
24 STDMETHODIMP_(ULONG
) Release()
26 InterlockedDecrement(&m_Ref
);
38 ULONG NTAPI
NumberOfEntries();
40 CResourceList(IUnknown
* OuterUnknown
) : m_OuterUnknown(OuterUnknown
), m_PoolType(NonPagedPool
), m_TranslatedResourceList(0), m_UntranslatedResourceList(0), m_NumberOfEntries(0) {}
41 virtual ~CResourceList() {}
44 PUNKNOWN m_OuterUnknown
;
46 PCM_RESOURCE_LIST m_TranslatedResourceList
;
47 PCM_RESOURCE_LIST m_UntranslatedResourceList
;
48 ULONG m_NumberOfEntries
;
56 CResourceList::QueryInterface(
60 UNICODE_STRING GuidString
;
62 if (IsEqualGUIDAligned(refiid
, IID_IResourceList
) ||
63 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
65 *Output
= PVOID(PRESOURCELIST(this));
66 PUNKNOWN(*Output
)->AddRef();
67 return STATUS_SUCCESS
;
70 if (RtlStringFromGUID(refiid
, &GuidString
) == STATUS_SUCCESS
)
72 DPRINT("IResourceList_QueryInterface no interface!!! iface %S\n", GuidString
.Buffer
);
73 RtlFreeUnicodeString(&GuidString
);
76 return STATUS_UNSUCCESSFUL
;
81 CResourceList::NumberOfEntries()
83 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
85 return m_NumberOfEntries
;
91 CResourceList::NumberOfEntriesOfType(
92 IN CM_RESOURCE_TYPE Type
)
94 ULONG Index
, Count
= 0;
95 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
, UnPartialDescriptor
;
97 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
99 if (!m_TranslatedResourceList
)
104 PC_ASSERT(m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
== m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
);
105 // I guess the translated and untranslated lists will be same length?
106 for (Index
= 0; Index
< m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
; Index
++ )
108 PartialDescriptor
= &m_TranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[Index
];
109 UnPartialDescriptor
= &m_UntranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[Index
];
110 DPRINT("Descriptor Type %u\n", PartialDescriptor
->Type
);
111 if (PartialDescriptor
->Type
== Type
)
113 // Yay! Finally found one that matches!
117 if (PartialDescriptor
->Type
== CmResourceTypeInterrupt
)
119 DPRINT("Index %u TRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\n", Index
, PartialDescriptor
->u
.Interrupt
.Affinity
, PartialDescriptor
->u
.Interrupt
.Level
, PartialDescriptor
->u
.Interrupt
.Vector
, PartialDescriptor
->Flags
, PartialDescriptor
->ShareDisposition
);
120 DPRINT("Index %u UNTRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\\n", Index
, UnPartialDescriptor
->u
.Interrupt
.Affinity
, UnPartialDescriptor
->u
.Interrupt
.Level
, UnPartialDescriptor
->u
.Interrupt
.Vector
, UnPartialDescriptor
->Flags
, UnPartialDescriptor
->ShareDisposition
);
123 else if (PartialDescriptor
->Type
== CmResourceTypePort
)
125 DPRINT("Index %u TRANS Port Length %u Start %u %u Flags %x Share %x\n", Index
, PartialDescriptor
->u
.Port
.Length
, PartialDescriptor
->u
.Port
.Start
.HighPart
, PartialDescriptor
->u
.Port
.Start
.LowPart
, PartialDescriptor
->Flags
, PartialDescriptor
->ShareDisposition
);
126 DPRINT("Index %u UNTRANS Port Length %u Start %u %u Flags %x Share %x\n", Index
, UnPartialDescriptor
->u
.Port
.Length
, UnPartialDescriptor
->u
.Port
.Start
.HighPart
, UnPartialDescriptor
->u
.Port
.Start
.LowPart
, UnPartialDescriptor
->Flags
, UnPartialDescriptor
->ShareDisposition
);
130 DPRINT("Found %d type %d\n", Count
, Type
);
134 PCM_PARTIAL_RESOURCE_DESCRIPTOR
136 CResourceList::FindTranslatedEntry(
137 IN CM_RESOURCE_TYPE Type
,
140 ULONG DescIndex
, Count
= 0;
141 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
143 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
145 if (!m_TranslatedResourceList
)
151 for (DescIndex
= 0; DescIndex
< m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
; DescIndex
++ )
153 PartialDescriptor
= &m_TranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[DescIndex
];
155 if (PartialDescriptor
->Type
== Type
)
157 // Yay! Finally found one that matches!
160 return PartialDescriptor
;
169 PCM_PARTIAL_RESOURCE_DESCRIPTOR
171 CResourceList::FindUntranslatedEntry(
172 IN CM_RESOURCE_TYPE Type
,
175 ULONG DescIndex
, Count
= 0;
176 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
178 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
180 if (!m_UntranslatedResourceList
)
186 for (DescIndex
= 0; DescIndex
< m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
; DescIndex
++ )
188 PartialDescriptor
= &m_UntranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[DescIndex
];
190 if (PartialDescriptor
->Type
== Type
)
192 // Yay! Finally found one that matches!
195 return PartialDescriptor
;
205 CResourceList::AddEntry(
206 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated
,
207 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated
)
209 PCM_RESOURCE_LIST NewUntranslatedResources
, NewTranslatedResources
;
210 ULONG NewTranslatedSize
, NewUntranslatedSize
, TranslatedSize
, UntranslatedSize
, ResourceCount
;
212 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
214 // calculate translated resource list size
215 ResourceCount
= m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
;
217 NewTranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
+1]);
218 TranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
220 NewTranslatedSize
= sizeof(CM_RESOURCE_LIST
) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + (ResourceCount
+1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
221 TranslatedSize
= sizeof(CM_RESOURCE_LIST
) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + (ResourceCount
) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
223 NewTranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(m_PoolType
, NewTranslatedSize
, TAG_PORTCLASS
);
224 if (!NewTranslatedResources
)
225 return STATUS_INSUFFICIENT_RESOURCES
;
228 // calculate untranslated resouce list size
229 ResourceCount
= m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
;
232 NewUntranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
+1]);
233 UntranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
235 NewUntranslatedSize
= sizeof(CM_RESOURCE_LIST
) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + (ResourceCount
+1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
236 UntranslatedSize
= sizeof(CM_RESOURCE_LIST
) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + (ResourceCount
) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
240 // allocate untranslated resource list size
241 NewUntranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(m_PoolType
, NewUntranslatedSize
, TAG_PORTCLASS
);
242 if (!NewUntranslatedResources
)
244 FreeItem(NewTranslatedResources
, TAG_PORTCLASS
);
245 return STATUS_INSUFFICIENT_RESOURCES
;
248 // now copy translated resource list
249 RtlMoveMemory(NewTranslatedResources
, m_TranslatedResourceList
, TranslatedSize
);
250 RtlMoveMemory((PUCHAR
)NewTranslatedResources
+ TranslatedSize
, Translated
, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
252 // now copy untranslated resource list
253 RtlMoveMemory(NewUntranslatedResources
, m_UntranslatedResourceList
, UntranslatedSize
);
254 RtlMoveMemory((PUCHAR
)NewUntranslatedResources
+ UntranslatedSize
, Untranslated
, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
257 FreeItem(m_TranslatedResourceList
, TAG_PORTCLASS
);
258 FreeItem(m_UntranslatedResourceList
, TAG_PORTCLASS
);
261 m_UntranslatedResourceList
= NewUntranslatedResources
;
262 m_TranslatedResourceList
= NewTranslatedResources
;
264 // increment descriptor count
265 NewUntranslatedResources
->List
[0].PartialResourceList
.Count
++;
266 NewTranslatedResources
->List
[0].PartialResourceList
.Count
++;
271 return STATUS_SUCCESS
;
276 CResourceList::AddEntryFromParent(
277 IN IResourceList
* Parent
,
278 IN CM_RESOURCE_TYPE Type
,
281 PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated
, Untranslated
;
283 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
285 Translated
= Parent
->FindTranslatedEntry(Type
, Index
);
286 Untranslated
= Parent
->FindUntranslatedEntry(Type
, Index
);
288 if (Translated
&& Untranslated
)
290 // add entry from parent
291 return AddEntry(Translated
, Untranslated
);
295 return STATUS_INVALID_PARAMETER
;
300 CResourceList::TranslatedList()
302 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
304 return m_TranslatedResourceList
;
309 CResourceList::UntranslatedList()
311 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
313 return m_UntranslatedResourceList
;
321 OUT PRESOURCELIST
* OutResourceList
,
322 IN PUNKNOWN OuterUnknown OPTIONAL
,
323 IN POOL_TYPE PoolType
,
324 IN PCM_RESOURCE_LIST TranslatedResourceList
,
325 IN PCM_RESOURCE_LIST UntranslatedResourceList
)
327 PCM_RESOURCE_LIST NewUntranslatedResources
, NewTranslatedResources
;
328 ULONG NewTranslatedSize
, NewUntranslatedSize
, ResourceCount
;
329 CResourceList
* NewList
;
332 if (!TranslatedResourceList
)
335 // if the untranslated resource list is also not provided, it becomes an empty resource list
337 if (UntranslatedResourceList
)
339 // invalid parameter mix
340 return STATUS_INVALID_PARAMETER
;
346 // if the translated resource list is also not provided, it becomes an empty resource list
348 if (!UntranslatedResourceList
)
350 // invalid parameter mix
351 return STATUS_INVALID_PARAMETER
;
355 NewList
= new(PoolType
, TAG_PORTCLASS
)CResourceList(OuterUnknown
);
357 return STATUS_INSUFFICIENT_RESOURCES
;
359 Status
= NewList
->QueryInterface(IID_IResourceList
, (PVOID
*)OutResourceList
);
361 if (!NT_SUCCESS(Status
))
367 return STATUS_INVALID_PARAMETER
;
370 if (!TranslatedResourceList
)
373 // empty resource list
375 return STATUS_SUCCESS
;
378 // calculate translated resource list size
379 ResourceCount
= TranslatedResourceList
->List
[0].PartialResourceList
.Count
;
381 NewTranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
383 NewTranslatedSize
= sizeof(CM_RESOURCE_LIST
) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + (ResourceCount
) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
386 // store resource count
387 NewList
->m_NumberOfEntries
= ResourceCount
;
389 // calculate untranslated resouce list size
390 ResourceCount
= UntranslatedResourceList
->List
[0].PartialResourceList
.Count
;
392 NewUntranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
394 NewUntranslatedSize
= sizeof(CM_RESOURCE_LIST
) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + (ResourceCount
) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
397 // allocate translated resource list
398 NewTranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, NewTranslatedSize
, TAG_PORTCLASS
);
399 if (!NewTranslatedResources
)
402 return STATUS_INSUFFICIENT_RESOURCES
;
405 // allocate untranslated resource list
406 NewUntranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, NewUntranslatedSize
, TAG_PORTCLASS
);
407 if (!NewUntranslatedResources
)
410 return STATUS_INSUFFICIENT_RESOURCES
;
413 // copy resource lists
414 RtlCopyMemory(NewTranslatedResources
, TranslatedResourceList
, NewTranslatedSize
);
415 RtlCopyMemory(NewUntranslatedResources
, UntranslatedResourceList
, NewUntranslatedSize
);
417 // store resource lists
418 NewList
->m_TranslatedResourceList
= NewTranslatedResources
;
419 NewList
->m_UntranslatedResourceList
= NewUntranslatedResources
;
421 return STATUS_SUCCESS
;
427 PcNewResourceSublist(
428 OUT PRESOURCELIST
* OutResourceList
,
429 IN PUNKNOWN OuterUnknown OPTIONAL
,
430 IN POOL_TYPE PoolType
,
431 IN PRESOURCELIST ParentList
,
432 IN ULONG MaximumEntries
)
434 CResourceList
* NewList
, *Parent
;
436 if (!OutResourceList
|| !ParentList
|| !MaximumEntries
)
437 return STATUS_INVALID_PARAMETER
;
439 Parent
= (CResourceList
*)ParentList
;
441 if (!Parent
->m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
||
442 !Parent
->m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
)
444 // parent list can't be empty
445 return STATUS_INVALID_PARAMETER
;
448 NewList
= new(PoolType
, TAG_PORTCLASS
) CResourceList(OuterUnknown
);
450 return STATUS_INSUFFICIENT_RESOURCES
;
452 NewList
->m_TranslatedResourceList
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, sizeof(CM_RESOURCE_LIST
), TAG_PORTCLASS
);
453 if (!NewList
->m_TranslatedResourceList
)
456 return STATUS_INSUFFICIENT_RESOURCES
;
459 NewList
->m_UntranslatedResourceList
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, sizeof(CM_RESOURCE_LIST
), TAG_PORTCLASS
);
460 if (!NewList
->m_UntranslatedResourceList
)
463 return STATUS_INSUFFICIENT_RESOURCES
;
466 RtlCopyMemory(NewList
->m_TranslatedResourceList
, Parent
->m_TranslatedResourceList
, sizeof(CM_RESOURCE_LIST
));
467 RtlCopyMemory(NewList
->m_UntranslatedResourceList
, Parent
->m_UntranslatedResourceList
, sizeof(CM_RESOURCE_LIST
));
469 // mark list as empty
470 NewList
->m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
= 0;
471 NewList
->m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
= 0;
473 NewList
->m_OuterUnknown
= OuterUnknown
;
474 NewList
->m_PoolType
= PoolType
;
476 NewList
->m_NumberOfEntries
= 0;
478 *OutResourceList
= (IResourceList
*)NewList
;
480 DPRINT("PcNewResourceSublist OutResourceList %p OuterUnknown %p ParentList %p\n", *OutResourceList
, OuterUnknown
, ParentList
);
481 return STATUS_SUCCESS
;