Sync to trunk head(r38096)
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / port_wavepci.c
1 #include "private.h"
2
3 typedef struct
4 {
5 IPortWavePciVtbl *lpVtbl;
6 IServiceSinkVtbl *lpVtblServiceSink;
7
8 #if 0
9 IUnregisterSubdevice *lpVtblUnregisterSubDevice;
10 IPortClsVersionVtbl *lpVtblPortClsVersion;
11 #endif
12 LONG ref;
13
14 PMINIPORTWAVEPCI Miniport;
15 PDEVICE_OBJECT pDeviceObject;
16 KDPC Dpc;
17 BOOL bInitialized;
18 PRESOURCELIST pResourceList;
19 PSERVICEGROUP ServiceGroup;
20 }IPortWavePciImpl;
21
22
23 const GUID IID_IPortWavePci;
24 const GUID IID_IMiniportWavePci;
25
26 //---------------------------------------------------------------
27 // IServiceSink
28 //
29
30 static
31 NTSTATUS
32 NTAPI
33 IServiceSink_fnQueryInterface(
34 IServiceSink* iface,
35 IN REFIID refiid,
36 OUT PVOID* Output)
37 {
38 IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
39
40 if (IsEqualGUIDAligned(refiid, &IID_IServiceSink))
41 {
42 *Output = &This->lpVtblServiceSink;
43 InterlockedIncrement(&This->ref);
44 return STATUS_SUCCESS;
45 }
46 return STATUS_UNSUCCESSFUL;
47 }
48
49 static
50 ULONG
51 NTAPI
52 IServiceSink_fnAddRef(
53 IServiceSink* iface)
54 {
55 IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
56
57 return InterlockedIncrement(&This->ref);
58 }
59
60 static
61 ULONG
62 NTAPI
63 IServiceSink_fnRelease(
64 IServiceSink* iface)
65 {
66 IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
67
68 InterlockedDecrement(&This->ref);
69
70 if (This->ref == 0)
71 {
72 ExFreePoolWithTag(This, TAG_PORTCLASS);
73 return 0;
74 }
75 /* Return new reference count */
76 return This->ref;
77 }
78
79 static
80 VOID
81 NTAPI
82 IServiceSink_fnRequestService(
83 IServiceSink* iface)
84 {
85 IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblServiceSink);
86
87 if (This->Miniport)
88 {
89 This->Miniport->lpVtbl->Service(This->Miniport);
90 }
91 }
92
93 static IServiceSinkVtbl vt_IServiceSink =
94 {
95 IServiceSink_fnQueryInterface,
96 IServiceSink_fnAddRef,
97 IServiceSink_fnRelease,
98 IServiceSink_fnRequestService
99 };
100
101 //---------------------------------------------------------------
102 // IPortWavePci
103 //
104
105 static
106 NTSTATUS
107 NTAPI
108 IPortWavePci_fnQueryInterface(
109 IPortWavePci* iface,
110 IN REFIID refiid,
111 OUT PVOID* Output)
112 {
113 IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
114
115 if (IsEqualGUIDAligned(refiid, &IID_IPortWavePci))
116 {
117 *Output = &This->lpVtbl;
118 InterlockedIncrement(&This->ref);
119 return STATUS_SUCCESS;
120 }
121 else if (IsEqualGUIDAligned(refiid, &IID_IServiceSink))
122 {
123 *Output = &This->lpVtbl;
124 InterlockedIncrement(&This->ref);
125 return STATUS_SUCCESS;
126 }
127 return STATUS_UNSUCCESSFUL;
128 }
129
130 static
131 ULONG
132 NTAPI
133 IPortWavePci_fnAddRef(
134 IPortWavePci* iface)
135 {
136 IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
137 return InterlockedIncrement(&This->ref);
138 }
139
140 static
141 ULONG
142 NTAPI
143 IPortWavePci_fnRelease(
144 IPortWavePci* iface)
145 {
146 IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
147
148 InterlockedDecrement(&This->ref);
149
150 if (This->ref == 0)
151 {
152 ExFreePoolWithTag(This, TAG_PORTCLASS);
153 return 0;
154 }
155 /* Return new reference count */
156 return This->ref;
157 }
158
159 VOID
160 NTAPI
161 ServiceNotifyRoutine(
162 IN struct _KDPC *Dpc,
163 IN PVOID DeferredContext,
164 IN PVOID SystemArgument1,
165 IN PVOID SystemArgument2)
166 {
167 IPortWavePciImpl * This = (IPortWavePciImpl*)DeferredContext;
168 if (This->ServiceGroup)
169 {
170 This->ServiceGroup->lpVtbl->RequestService(This->ServiceGroup);
171 }
172 }
173
174
175
176 NTSTATUS
177 NTAPI
178 IPortWavePci_fnInit(
179 IN IPortWavePci * iface,
180 IN PDEVICE_OBJECT DeviceObject,
181 IN PIRP Irp,
182 IN PUNKNOWN UnknownMiniport,
183 IN PUNKNOWN UnknownAdapter OPTIONAL,
184 IN PRESOURCELIST ResourceList)
185 {
186 IMiniportWavePci * Miniport;
187 PSERVICEGROUP ServiceGroup;
188 NTSTATUS Status;
189 IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
190
191 if (This->bInitialized)
192 {
193 DPRINT("IPortWaveCyclic_Init called again\n");
194 return STATUS_SUCCESS;
195 }
196
197 Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportWavePci, (PVOID*)&Miniport);
198 if (!NT_SUCCESS(Status))
199 {
200 DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n");
201 return STATUS_INVALID_PARAMETER;
202 }
203
204 Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup);
205 if (!NT_SUCCESS(Status))
206 {
207 DPRINT("IMiniportWaveCyclic_Init failed with %x\n", Status);
208 return Status;
209 }
210
211 /* Initialize port object */
212 This->Miniport = Miniport;
213 This->pDeviceObject = DeviceObject;
214 This->bInitialized = TRUE;
215 This->pResourceList = ResourceList;
216 This->ServiceGroup = ServiceGroup;
217
218 /* initialize the dpc */
219 KeInitializeDpc(&This->Dpc, ServiceNotifyRoutine, (PVOID)This);
220
221 /* increment reference on miniport adapter */
222 Miniport->lpVtbl->AddRef(Miniport);
223 /* increment reference on resource list */
224 ResourceList->lpVtbl->AddRef(ResourceList);
225
226 /* add ourselves to service group which is called when miniport receives an isr */
227 ServiceGroup->lpVtbl->AddMember(ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
228
229 /* increment reference on service group */
230 ServiceGroup->lpVtbl->AddRef(ServiceGroup);
231
232 return STATUS_SUCCESS;
233 }
234
235 NTSTATUS
236 NTAPI
237 IPortWavePci_fnNewRegistryKey(
238 IN IPortWavePci * iface,
239 OUT PREGISTRYKEY *OutRegistryKey,
240 IN PUNKNOWN OuterUnknown OPTIONAL,
241 IN ULONG RegistryKeyType,
242 IN ACCESS_MASK DesiredAccess,
243 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
244 IN ULONG CreateOptions OPTIONAL,
245 OUT PULONG Disposition OPTIONAL)
246 {
247 return STATUS_UNSUCCESSFUL;
248 }
249
250 NTSTATUS
251 NTAPI
252 IPortWavePci_fnGetDeviceProperty(
253 IN IPortWavePci * iface,
254 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
255 IN ULONG BufferLength,
256 OUT PVOID PropertyBuffer,
257 OUT PULONG ReturnLength)
258 {
259 IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
260
261 if (!This->bInitialized)
262 {
263 DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initiazed\n");
264 return STATUS_UNSUCCESSFUL;
265 }
266
267 return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
268 }
269
270 NTSTATUS
271 NTAPI
272 IPortWavePci_fnNewMasterDmaChannel(
273 IN IPortWavePci * iface,
274 OUT PDMACHANNEL* DmaChannel,
275 IN PUNKNOWN OuterUnknown,
276 IN POOL_TYPE PoolType,
277 IN PRESOURCELIST ResourceList OPTIONAL,
278 IN BOOL ScatterGather,
279 IN BOOL Dma32BitAddresses,
280 IN BOOL Dma64BitAddresses,
281 IN DMA_WIDTH DmaWidth,
282 IN DMA_SPEED DmaSpeed,
283 IN ULONG MaximumLength,
284 IN ULONG DmaPort)
285 {
286 return STATUS_UNSUCCESSFUL;
287 }
288
289 VOID
290 NTAPI
291 IPortWavePci_fnNotify(
292 IN IPortWavePci * iface,
293 IN PSERVICEGROUP ServiceGroup)
294 {
295 IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
296 KeInsertQueueDpc(&This->Dpc, NULL, NULL);
297 }
298
299 static IPortWavePciVtbl vt_IPortWavePci =
300 {
301 /* IUnknown methods */
302 IPortWavePci_fnQueryInterface,
303 IPortWavePci_fnAddRef,
304 IPortWavePci_fnRelease,
305 /* IPort methods */
306 IPortWavePci_fnInit,
307 IPortWavePci_fnGetDeviceProperty,
308 IPortWavePci_fnNewRegistryKey,
309 /* IPortWavePci methods */
310 IPortWavePci_fnNewMasterDmaChannel,
311 IPortWavePci_fnNotify
312 };
313
314
315 NTSTATUS
316 NewPortWavePci(
317 OUT PPORT* OutPort)
318 {
319 IPortWavePciImpl * This;
320
321 This = ExAllocatePoolWithTag(NonPagedPool, sizeof(IPortWavePciImpl), TAG_PORTCLASS);
322 if (!This)
323 return STATUS_INSUFFICIENT_RESOURCES;
324
325 RtlZeroMemory(This, sizeof(IPortWavePciImpl));
326 This->lpVtblServiceSink = &vt_IServiceSink;
327 This->lpVtbl = &vt_IPortWavePci;
328 This->ref = 1;
329
330 *OutPort = (PPORT)&This->lpVtbl;
331 return STATUS_SUCCESS;
332 }