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