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