1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS Kernel Streaming
4c2c66affSColin Finck  * FILE:            drivers/wdm/audio/backpln/portcls/port_wavertstream.cpp
5c2c66affSColin Finck  * PURPOSE:         WaveRTStream helper object
6c2c66affSColin Finck  * PROGRAMMER:      Johannes Anderwald
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include "private.hpp"
10c2c66affSColin Finck 
11c2c66affSColin Finck #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck 
14*6e97b431SVictor Perevertkin class CPortWaveRTStreamInit : public CUnknownImpl<IPortWaveRTStreamInit>
15c2c66affSColin Finck {
16c2c66affSColin Finck public:
17c2c66affSColin Finck     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18c2c66affSColin Finck 
19c2c66affSColin Finck     IMP_IPortWaveRTStreamInit;
CPortWaveRTStreamInit(IUnknown * OuterUnknown)20c2c66affSColin Finck     CPortWaveRTStreamInit(IUnknown *OuterUnknown) {}
~CPortWaveRTStreamInit()21c2c66affSColin Finck     virtual ~CPortWaveRTStreamInit() {}
22c2c66affSColin Finck 
23c2c66affSColin Finck };
24c2c66affSColin Finck 
25c2c66affSColin Finck NTSTATUS
26c2c66affSColin Finck NTAPI
QueryInterface(IN REFIID refiid,OUT PVOID * Output)27c2c66affSColin Finck CPortWaveRTStreamInit::QueryInterface(
28c2c66affSColin Finck     IN  REFIID refiid,
29c2c66affSColin Finck     OUT PVOID* Output)
30c2c66affSColin Finck {
31c2c66affSColin Finck 
32c2c66affSColin Finck     DPRINT("IPortWaveRTStream_fnQueryInterface entered\n");
33c2c66affSColin Finck 
34c2c66affSColin Finck     if (IsEqualGUIDAligned(refiid, IID_IPortWaveRTStream) ||
35c2c66affSColin Finck         IsEqualGUIDAligned(refiid, IID_IUnknown))
36c2c66affSColin Finck     {
37c2c66affSColin Finck         *Output = PVOID(PPORTWAVERTSTREAM(this));
38c2c66affSColin Finck         PUNKNOWN(*Output)->AddRef();
39c2c66affSColin Finck         return STATUS_SUCCESS;
40c2c66affSColin Finck     }
41c2c66affSColin Finck     return STATUS_UNSUCCESSFUL;
42c2c66affSColin Finck }
43c2c66affSColin Finck 
44c2c66affSColin Finck PMDL
45c2c66affSColin Finck NTAPI
AllocatePagesForMdl(IN PHYSICAL_ADDRESS HighAddress,IN SIZE_T TotalBytes)46c2c66affSColin Finck CPortWaveRTStreamInit::AllocatePagesForMdl(
47c2c66affSColin Finck     IN PHYSICAL_ADDRESS HighAddress,
48c2c66affSColin Finck     IN SIZE_T TotalBytes)
49c2c66affSColin Finck {
50c2c66affSColin Finck     return MmAllocatePagesForMdl(RtlConvertUlongToLargeInteger(0), HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes);
51c2c66affSColin Finck }
52c2c66affSColin Finck 
53c2c66affSColin Finck PMDL
54c2c66affSColin Finck NTAPI
AllocateContiguousPagesForMdl(IN PHYSICAL_ADDRESS LowAddress,IN PHYSICAL_ADDRESS HighAddress,IN SIZE_T TotalBytes)55c2c66affSColin Finck CPortWaveRTStreamInit::AllocateContiguousPagesForMdl(
56c2c66affSColin Finck     IN PHYSICAL_ADDRESS LowAddress,
57c2c66affSColin Finck     IN PHYSICAL_ADDRESS HighAddress,
58c2c66affSColin Finck     IN SIZE_T TotalBytes)
59c2c66affSColin Finck {
60c2c66affSColin Finck     PMDL Mdl;
61c2c66affSColin Finck     PVOID Buffer;
62c2c66affSColin Finck     PHYSICAL_ADDRESS Address;
63c2c66affSColin Finck 
64c2c66affSColin Finck     Buffer = MmAllocateContiguousMemorySpecifyCache(TotalBytes, LowAddress, HighAddress, RtlConvertUlongToLargeInteger(0), MmNonCached);
65c2c66affSColin Finck     if (!Buffer)
66c2c66affSColin Finck     {
67c2c66affSColin Finck         DPRINT("MmAllocateContiguousMemorySpecifyCache failed\n");
68c2c66affSColin Finck         return NULL;
69c2c66affSColin Finck     }
70c2c66affSColin Finck 
71c2c66affSColin Finck     Address = MmGetPhysicalAddress(Buffer);
72c2c66affSColin Finck 
73c2c66affSColin Finck     MmFreeContiguousMemorySpecifyCache(Buffer, TotalBytes, MmNonCached);
74c2c66affSColin Finck 
75c2c66affSColin Finck     Mdl = MmAllocatePagesForMdl(Address, HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes);
76c2c66affSColin Finck     if (!Mdl)
77c2c66affSColin Finck     {
78c2c66affSColin Finck         DPRINT("MmAllocatePagesForMdl failed\n");
79c2c66affSColin Finck         return NULL;
80c2c66affSColin Finck     }
81c2c66affSColin Finck 
82c2c66affSColin Finck     if (MmGetMdlByteCount(Mdl) < TotalBytes)
83c2c66affSColin Finck     {
84c2c66affSColin Finck         DPRINT("ByteCount %u Required %u\n", MmGetMdlByteCount(Mdl), TotalBytes);
85c2c66affSColin Finck         MmFreePagesFromMdl(Mdl);
86c2c66affSColin Finck         ExFreePool(Mdl);
87c2c66affSColin Finck         return NULL;
88c2c66affSColin Finck     }
89c2c66affSColin Finck 
90c2c66affSColin Finck     DPRINT("Result %p\n", Mdl);
91c2c66affSColin Finck     return Mdl;
92c2c66affSColin Finck }
93c2c66affSColin Finck 
94c2c66affSColin Finck PVOID
95c2c66affSColin Finck NTAPI
MapAllocatedPages(IN PMDL MemoryDescriptorList,IN MEMORY_CACHING_TYPE CacheType)96c2c66affSColin Finck CPortWaveRTStreamInit::MapAllocatedPages(
97c2c66affSColin Finck     IN PMDL MemoryDescriptorList,
98c2c66affSColin Finck     IN MEMORY_CACHING_TYPE CacheType)
99c2c66affSColin Finck {
100c2c66affSColin Finck     return MmMapLockedPagesSpecifyCache(MemoryDescriptorList, KernelMode, CacheType, NULL, 0, NormalPagePriority);
101c2c66affSColin Finck }
102c2c66affSColin Finck 
103c2c66affSColin Finck VOID
104c2c66affSColin Finck NTAPI
UnmapAllocatedPages(IN PVOID BaseAddress,IN PMDL MemoryDescriptorList)105c2c66affSColin Finck CPortWaveRTStreamInit::UnmapAllocatedPages(
106c2c66affSColin Finck     IN PVOID   BaseAddress,
107c2c66affSColin Finck     IN PMDL MemoryDescriptorList)
108c2c66affSColin Finck {
109c2c66affSColin Finck     MmUnmapLockedPages(BaseAddress, MemoryDescriptorList);
110c2c66affSColin Finck }
111c2c66affSColin Finck 
112c2c66affSColin Finck VOID
113c2c66affSColin Finck NTAPI
FreePagesFromMdl(IN PMDL MemoryDescriptorList)114c2c66affSColin Finck CPortWaveRTStreamInit::FreePagesFromMdl(
115c2c66affSColin Finck     IN PMDL MemoryDescriptorList)
116c2c66affSColin Finck {
117c2c66affSColin Finck     MmFreePagesFromMdl(MemoryDescriptorList);
118c2c66affSColin Finck     ExFreePool(MemoryDescriptorList);
119c2c66affSColin Finck }
120c2c66affSColin Finck 
121c2c66affSColin Finck ULONG
122c2c66affSColin Finck NTAPI
GetPhysicalPagesCount(IN PMDL MemoryDescriptorList)123c2c66affSColin Finck CPortWaveRTStreamInit::GetPhysicalPagesCount(
124c2c66affSColin Finck     IN PMDL MemoryDescriptorList)
125c2c66affSColin Finck {
126c2c66affSColin Finck     return ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
127c2c66affSColin Finck }
128c2c66affSColin Finck 
129c2c66affSColin Finck PHYSICAL_ADDRESS
130c2c66affSColin Finck NTAPI
GetPhysicalPageAddress(IN PPHYSICAL_ADDRESS Address,IN PMDL MemoryDescriptorList,IN ULONG Index)131c2c66affSColin Finck CPortWaveRTStreamInit::GetPhysicalPageAddress(
132c2c66affSColin Finck     IN PPHYSICAL_ADDRESS Address,
133c2c66affSColin Finck     IN PMDL MemoryDescriptorList,
134c2c66affSColin Finck     IN ULONG Index)
135c2c66affSColin Finck {
136c2c66affSColin Finck     PVOID Buffer;
137c2c66affSColin Finck     ULONG Pages;
138c2c66affSColin Finck     PHYSICAL_ADDRESS Result, Addr;
139c2c66affSColin Finck 
140c2c66affSColin Finck     Pages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
141c2c66affSColin Finck     if (Pages <= Index)
142c2c66affSColin Finck     {
143c2c66affSColin Finck         DPRINT("OutOfBounds: Pages %u Index %u\n", Pages, Index);
144c2c66affSColin Finck         return RtlConvertUlongToLargeInteger(0);
145c2c66affSColin Finck     }
146c2c66affSColin Finck 
147c2c66affSColin Finck     Buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(MemoryDescriptorList, LowPagePriority) + (Index * PAGE_SIZE);
148c2c66affSColin Finck 
149c2c66affSColin Finck     Addr = MmGetPhysicalAddress(Buffer);
150c2c66affSColin Finck     Address->QuadPart = Addr.QuadPart;
151c2c66affSColin Finck     Result.QuadPart = (ULONG_PTR)Address;
152c2c66affSColin Finck 
153c2c66affSColin Finck     return Result;
154c2c66affSColin Finck }
155c2c66affSColin Finck 
156c2c66affSColin Finck NTSTATUS
NewPortWaveRTStream(PPORTWAVERTSTREAM * OutStream)157c2c66affSColin Finck NewPortWaveRTStream(
158c2c66affSColin Finck     PPORTWAVERTSTREAM *OutStream)
159c2c66affSColin Finck {
160c2c66affSColin Finck     NTSTATUS Status;
161c2c66affSColin Finck     CPortWaveRTStreamInit* This = new(NonPagedPool, TAG_PORTCLASS) CPortWaveRTStreamInit(NULL);
162c2c66affSColin Finck     if (!This)
163c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
164c2c66affSColin Finck 
165c2c66affSColin Finck     Status = This->QueryInterface(IID_IPortWaveRTStream, (PVOID*)OutStream);
166c2c66affSColin Finck 
167c2c66affSColin Finck     if (!NT_SUCCESS(Status))
168c2c66affSColin Finck     {
169c2c66affSColin Finck         delete This;
170c2c66affSColin Finck         return Status;
171c2c66affSColin Finck     }
172c2c66affSColin Finck 
173c2c66affSColin Finck     *OutStream = (PPORTWAVERTSTREAM)This;
174c2c66affSColin Finck     return Status;
175c2c66affSColin Finck }
176