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