- Fix building of cmidriver
[reactos.git] / reactos / drivers / wdm / audio / drivers / CMIDriver / minwave.cpp
1 /*
2 Copyright (c) 2006-2007 dogbert <dogber1@gmail.com>
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "minwave.hpp"
29 #include "minwavetables.hpp"
30 #include "ntddk.h"
31
32 #pragma code_seg("PAGE")
33
34 HRESULT NTAPI CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType)
35 {
36 //PAGED_CODE();
37 //ASSERT(Unknown);
38 #ifdef WAVERT
39 STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVERT);
40 #else
41 STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVECYCLIC);
42 #endif
43 }
44
45 NTSTATUS CMiniportWaveCMI::processResources(PRESOURCELIST resourceList)
46 {
47 //PAGED_CODE();
48 //ASSERT (resourceList);
49 DBGPRINT(("CMiniportWaveCMI[%p]::ProcessResources(%p)", this, resourceList));
50
51 if (resourceList->NumberOfInterrupts() < 1) {
52 DBGPRINT(("Unknown configuration for wave miniport"));
53 return STATUS_DEVICE_CONFIGURATION_ERROR;
54 }
55 return STATUS_SUCCESS;
56 }
57
58 #ifndef WAVERT
59 NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferLength)
60 {
61 //PAGED_CODE();
62 //ASSERT(dmaChannel);
63 DBGPRINT(("CMiniportWaveCMI[%p]::newDMAChannel(%p)", this, dmaChannel));
64
65 NTSTATUS ntStatus;
66
67 ntStatus = Port->NewMasterDmaChannel(dmaChannel, NULL, NULL, bufferLength, TRUE, FALSE, (DMA_WIDTH)(-1), (DMA_SPEED)(-1));
68 if (NT_SUCCESS(ntStatus)) {
69 ULONG lDMABufferLength = bufferLength;
70 do {
71 ntStatus = (*dmaChannel)->AllocateBuffer(lDMABufferLength,NULL);
72 lDMABufferLength >>= 1;
73 } while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2)));
74 }
75 return ntStatus;
76 }
77 #endif
78
79 //generic crap
80 STDMETHODIMP CMiniportWaveCMI::QueryInterface(REFIID Interface, PVOID *Object)
81 {
82 //PAGED_CODE();
83 //ASSERT(Object);
84 DBGPRINT(("CMiniportWaveCMI[%p]::NonDelegatingQueryInterface"));
85
86 if (IsEqualGUIDAligned(Interface,IID_IUnknown)) {
87 #ifdef WAVERT
88 *Object = PVOID(PUNKNOWN(PMINIPORTWAVERT(this)));
89 #else
90 *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this)));
91 #endif
92 } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) {
93 *Object = PVOID(PMINIPORT(this));
94 #ifdef WAVERT
95 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRT)) {
96 *Object = PVOID(PMINIPORTWAVERT(this));
97 #else
98 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclic)) {
99 *Object = PVOID(PMINIPORTWAVECYCLIC(this));
100 #endif
101 } else {
102 *Object = NULL;
103 }
104
105 if (*Object) {
106 // We reference the interface for the caller.
107 PUNKNOWN(*Object)->AddRef();
108 return STATUS_SUCCESS;
109 }
110
111 return STATUS_INVALID_PARAMETER;
112 }
113
114 CMiniportWaveCMI::~CMiniportWaveCMI(void)
115 {
116 //PAGED_CODE();
117 DBGPRINT(("CMiniportWaveCMI[%p]::~CMiniportWaveCMI", this));
118
119 storeChannelConfigToRegistry(); //or not. during system shutdown, this doesn't seem to work.
120
121 if (CMIAdapter) {
122 CMIAdapter->Release();
123 CMIAdapter = NULL;
124 }
125
126 for (int i=0;i<3;i++) {
127 #ifndef WAVERT
128 if (DMAChannel[i]) {
129 DMAChannel[i]->Release();
130 DMAChannel[i] = NULL;
131 }
132 #endif
133 if (isStreamRunning[i]) {
134 isStreamRunning[i] = false;
135 stream[i]->Release();
136 stream[i] = NULL;
137 }
138 }
139
140 if (Port) {
141 Port->Release();
142 Port = NULL;
143 }
144 }
145
146 #ifdef WAVERT
147 STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVERT Port_)
148 #else
149 STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVECYCLIC Port_)
150 #endif
151 {
152 //PAGED_CODE();
153
154 //ASSERT(UnknownAdapter);
155 //ASSERT(ResourceList);
156 //ASSERT(Port_);
157
158 DBGPRINT(("CMiniportWaveCMI[%p]::Init(%p, %p, %p)", this, UnknownAdapter, ResourceList, Port_));
159
160 Port = Port_;
161 Port->AddRef();
162
163 NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *) &CMIAdapter);
164 if (!NT_SUCCESS(ntStatus)) {
165 DBGPRINT(("QueryInterface(CMIAdapter) failed"));
166 return ntStatus;
167 }
168
169 //check for Vista, set the AC3 stuff accordingly
170 if (IoIsWdmVersionAvailable(0x06,0x00)) {
171 WavePinDataRangesAC3Stream[1].MinimumSampleFrequency = MIN_SAMPLE_RATE;
172 WavePinDataRangesAC3Stream[1].MaximumSampleFrequency = MAX_SAMPLE_RATE;
173 WavePinDataRangesAC3Stream[1].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
174 WavePinDataRangesAC3Stream[1].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
175 }
176
177 cm = CMIAdapter->getCMI8738Info();
178 cm->regFUNCTRL0 = 0;
179 cm->WaveMiniport = this;
180
181 loadChannelConfigFromRegistry();
182
183 for (int i=0;i<3;i++)
184 {
185 isStreamRunning[i] = false;
186
187 #ifndef WAVERT
188 ntStatus = newDMAChannel(&DMAChannel[i], MAXLEN_DMA_BUFFER);
189 if (!NT_SUCCESS(ntStatus)) {
190 DBGPRINT(("NewDmaChannel() failed"));
191 return ntStatus;
192 }
193 #endif
194 }
195
196 KeInitializeMutex(&mutex, 1);
197
198 return processResources(ResourceList);
199 }
200
201 #ifdef WAVERT
202 STDMETHODIMP_(NTSTATUS) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTION OutDeviceDescriptor)
203 {
204 //PAGED_CODE();
205 //ASSERT(OutDeviceDescriptor);
206 DBGPRINT(("CMiniportWaveCMI[%p]::GetDeviceDescription(%p)", this, OutDeviceDescriptor));
207
208 RtlZeroMemory(OutDeviceDescriptor, sizeof(DEVICE_DESCRIPTION));
209 OutDeviceDescriptor->ScatterGather = false;
210 OutDeviceDescriptor->Master = true;
211 OutDeviceDescriptor->Dma32BitAddresses = true;
212 OutDeviceDescriptor->InterfaceType = PCIBus;
213 OutDeviceDescriptor->MaximumLength = MAXLEN_DMA_BUFFER-2;
214
215 return STATUS_SUCCESS;
216 }
217 #endif
218
219 STDMETHODIMP CMiniportWaveCMI::GetDescription(PPCFILTER_DESCRIPTOR *OutFilterDescriptor)
220 {
221 //PAGED_CODE();
222 //ASSERT(OutFilterDescriptor);
223 DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor));
224
225 *OutFilterDescriptor = &WaveMiniportFilterDescriptor;
226
227 return STATUS_SUCCESS;
228 }
229
230 NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry()
231 {
232 //PAGED_CODE();
233 PREGISTRYKEY DriverKey;
234 PREGISTRYKEY SettingsKey;
235 UNICODE_STRING KeyName;
236 DWORD Value, ResultLength;
237 PVOID KeyInfo;
238
239 DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()"));
240
241 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) {
242 return STATUS_UNSUCCESSFUL;
243 }
244
245 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL);
246
247 if(!NT_SUCCESS(ntStatus)) {
248 DBGPRINT(("PcNewRegistryKey() failed"));
249 return STATUS_UNSUCCESSFUL;
250 }
251
252 RtlInitUnicodeString(&KeyName, L"Settings");
253
254 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL);
255 if(!NT_SUCCESS(ntStatus)) {
256 DBGPRINT(("DriverKey->NewSubKey() failed"));
257 return STATUS_UNSUCCESSFUL;
258 }
259
260 KeyInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), 'gnaa');
261 if (KeyInfo) {
262 RtlInitUnicodeString(&KeyName, L"ChannelCount");
263 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
264 if (NT_SUCCESS (ntStatus)) {
265 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
266 if (PartialInfo->DataLength == sizeof(DWORD)) {
267 requestedChannelCount = (*(PLONG)PartialInfo->Data);
268 }
269 } else {
270 requestedChannelCount = 2;
271 }
272
273 RtlInitUnicodeString(&KeyName, L"ChannelMask");
274 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
275 if (NT_SUCCESS (ntStatus)) {
276 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
277 if (PartialInfo->DataLength == sizeof(DWORD)) {
278 requestedChannelMask = (*(PLONG)PartialInfo->Data);
279 }
280 } else {
281 requestedChannelMask = KSAUDIO_SPEAKER_STEREO;
282 }
283 }
284 ExFreePoolWithTag(KeyInfo,'gnaa');
285
286 SettingsKey->Release();
287 DriverKey->Release();
288
289 return STATUS_SUCCESS;
290 }
291
292 NTSTATUS CMiniportWaveCMI::storeChannelConfigToRegistry()
293 {
294 //PAGED_CODE();
295 PREGISTRYKEY DriverKey;
296 PREGISTRYKEY SettingsKey;
297 UNICODE_STRING KeyName;
298 DWORD Value;
299 DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()"));
300
301 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) {
302 return STATUS_UNSUCCESSFUL;
303 }
304
305 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL);
306
307 if(!NT_SUCCESS(ntStatus)) {
308 DBGPRINT(("PcNewRegistryKey() failed"));
309 return STATUS_UNSUCCESSFUL;
310 }
311
312 RtlInitUnicodeString(&KeyName, L"Settings");
313
314 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL);
315 if(!NT_SUCCESS(ntStatus)) {
316 DBGPRINT(("DriverKey->NewSubKey() failed"));
317 return STATUS_UNSUCCESSFUL;
318 }
319
320 Value = requestedChannelCount;
321 RtlInitUnicodeString(&KeyName, L"ChannelCount");
322 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
323 if (!NT_SUCCESS(ntStatus)) {
324 DBGPRINT(("SetValueKey() failed"));
325 }
326 Value = requestedChannelMask;
327 RtlInitUnicodeString(&KeyName, L"ChannelMask");
328 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
329 if (!NT_SUCCESS(ntStatus)) {
330 DBGPRINT(("SetValueKey() failed"));
331 }
332
333 SettingsKey->Release();
334 DriverKey->Release();
335
336 return STATUS_SUCCESS;
337 }
338
339
340 STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void)
341 {
342 //PAGED_CODE();
343 DBGPRINT(("CMiniportWaveCMI[%p]::powerUp()", this));
344 KSSTATE oldState[3];
345
346 for (int i=0;i<3;i++) {
347 if (isStreamRunning[i]) {
348 oldState[i] = stream[i]->state;
349 stream[i]->SetState(KSSTATE_STOP);
350 }
351 }
352
353 if (cm->TopoMiniport) {
354 cm->TopoMiniport->loadMixerSettingsFromMemory();
355 }
356
357 for (int i=0;i<3;i++) {
358 if (isStreamRunning[i]) {
359 stream[i]->prepareStream();
360 stream[i]->SetState(KSSTATE_ACQUIRE);
361 stream[i]->SetState(oldState[i]);
362 }
363 }
364 }
365
366 STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void)
367 {
368 //PAGED_CODE();
369 DBGPRINT(("CMiniportWaveCMI[%p]::powerDown()", this));
370
371 if (cm->TopoMiniport) {
372 cm->TopoMiniport->storeMixerSettingsToMemory();
373 }
374
375 }
376
377
378 NTSTATUS CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, BOOLEAN AC3)
379 {
380 //PAGED_CODE();
381 //ASSERT(sampleRate);
382 DBGPRINT(("CMiniportWaveCMI[%p]::isFormatAllowed(%d, %d, %d)", this, sampleRate, multiChan, AC3));
383
384 if (multiChan) {
385 switch (sampleRate) {
386 case 44100: if (cm->formatMask & FMT_441_MULTI_PCM) return STATUS_SUCCESS; break;
387 case 48000: if (cm->formatMask & FMT_480_MULTI_PCM) return STATUS_SUCCESS; break;
388 case 88200: if (cm->formatMask & FMT_882_MULTI_PCM) return STATUS_SUCCESS; break;
389 case 96000: if (cm->formatMask & FMT_960_MULTI_PCM) return STATUS_SUCCESS; break;
390 }
391 return STATUS_INVALID_PARAMETER;
392 }
393 if (AC3) {
394 switch (sampleRate) {
395 case 44100: if (cm->formatMask & FMT_441_DOLBY) return STATUS_SUCCESS; break;
396 case 48000: if (cm->formatMask & FMT_480_DOLBY) return STATUS_SUCCESS; break;
397 case 88200: if (cm->formatMask & FMT_882_DOLBY) return STATUS_SUCCESS; break;
398 case 96000: if (cm->formatMask & FMT_960_DOLBY) return STATUS_SUCCESS; break;
399 }
400 return STATUS_INVALID_PARAMETER;
401 }
402 switch (sampleRate) {
403 case 44100: if (cm->formatMask & FMT_441_PCM) return STATUS_SUCCESS; break;
404 case 48000: if (cm->formatMask & FMT_480_PCM) return STATUS_SUCCESS; break;
405 case 88200: if (cm->formatMask & FMT_882_PCM) return STATUS_SUCCESS; break;
406 case 96000: if (cm->formatMask & FMT_960_PCM) return STATUS_SUCCESS; break;
407 }
408 return STATUS_INVALID_PARAMETER;
409 }
410
411 NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOOLEAN capture)
412 {
413 //PAGED_CODE();
414 //ASSERT(format);
415 DBGPRINT(("CMiniportWaveCMI[%p]::validateFormat(%p, %d, %d)", this, format, PinID, capture));
416
417 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(format + 1);
418 DBGPRINT(("---channels: %d, resolution: %d, sample rate: %d, pin: %d, formatMask: %x", waveFormat->nChannels, waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, PinID, cm->formatMask));
419
420 //WaveFormatEx
421 if ( ( format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX))
422 && IsEqualGUIDAligned(format->MajorFormat,KSDATAFORMAT_TYPE_AUDIO)
423 && IsEqualGUIDAligned(format->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ) {
424 switch (EXTRACT_WAVEFORMATEX_ID(&format->SubFormat)) {
425 case WAVE_FORMAT_PCM:
426 if ((PinID != PIN_WAVE_RENDER_SINK) && (PinID != PIN_WAVE_CAPTURE_SOURCE) && (PinID != -1)) {
427 if ((PinID == PIN_WAVE_AC3_RENDER_SINK) && !IoIsWdmVersionAvailable(6,0)) {
428 return STATUS_INVALID_PARAMETER;
429 }
430 }
431
432 if ( ((waveFormat->wBitsPerSample == 16) || (waveFormat->wBitsPerSample == 24))
433 && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000) || (waveFormat->nSamplesPerSec == 88200) || (waveFormat->nSamplesPerSec == 96000))
434 && (waveFormat->nChannels == 2) ) {
435 if ((capture) && (waveFormat->nSamplesPerSec > 48000) ) {
436 return STATUS_INVALID_PARAMETER;
437 }
438 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, FALSE);
439 }
440 if ( (waveFormat->wBitsPerSample == 16)
441 && ((waveFormat->nChannels >= 4) && (waveFormat->nChannels <= cm->maxChannels))
442 && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000)) ) {
443 #if OUT_CHANNEL == 1
444 if ((PinID == PIN_WAVE_RENDER_SINK) || (PinID == -1)) {
445 return isFormatAllowed(waveFormat->nSamplesPerSec, TRUE, FALSE);
446 }
447 #else
448 return STATUS_INVALID_PARAMETER;
449 #endif
450 }
451 break;
452 case WAVE_FORMAT_DOLBY_AC3_SPDIF:
453 if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != -1)) {
454 return STATUS_INVALID_PARAMETER;
455 }
456 if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_AC3) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_AC3))
457 && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_AC3) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_AC3))
458 && (waveFormat->nChannels == MAX_CHANNELS_AC3) ) {
459 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE);
460 }
461 break;
462 }
463 }
464
465 return STATUS_INVALID_PARAMETER;
466 }
467
468 // Tests a data range intersection
469 STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE ClientDataRange, PKSDATARANGE MyDataRange, ULONG OutputBufferLength, PVOID ResultantFormat, PULONG ResultantFormatLength)
470 {
471 //PAGED_CODE();
472 DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength));
473
474 if (PinId == PIN_WAVE_AC3_RENDER_SINK) {
475 bool isAC3Pin = true;
476 // Under Windows 2000 and XP, the client's DataRange should be AC3 only.
477 // The AC3 pin is the SPDIF pin in Windows Vista, so 2ch stereo is going to be allowed.
478
479 if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO)
480 && !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) {
481 return STATUS_NO_MATCH;
482 }
483
484
485 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, GUID_NULL)//KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) //HACK
486 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
487 // check for Vista
488 isAC3Pin = false;
489 if (IoIsWdmVersionAvailable(0x06,0x00)) {
490 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM)
491 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
492 return STATUS_NO_MATCH;
493 }
494 } else {
495 return STATUS_NO_MATCH;
496 }
497 }
498
499 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
500 || IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
501 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
502 } else
503 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
504 *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND);
505 } else {
506 return STATUS_NO_MATCH;
507 }
508
509 // Validate return buffer size, if the request is only for the
510 // size of the resultant structure, return it now.
511 if (!OutputBufferLength) {
512 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
513 return STATUS_BUFFER_OVERFLOW;
514 } else
515 if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
516 return STATUS_BUFFER_TOO_SMALL;
517 }
518
519 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
520 PWAVEFORMATEX pWaveFormatEx;
521
522 // Return the best (only) available format.
523 resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength;
524 resultantFormatWFX->DataFormat.Flags = 0;
525 resultantFormatWFX->DataFormat.SampleSize = 4; // must match nBlockAlign
526 resultantFormatWFX->DataFormat.Reserved = 0;
527
528 resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
529 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_DOLBY_AC3_SPDIF);
530
531 // Extra space for the DSound specifier
532 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
533
534 PKSDATAFORMAT_DSOUND resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat;
535
536 resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;
537
538 // DSound format capabilities are not expressed
539 // this way in KS, so we express no capabilities.
540 resultantFormatDSound->BufferDesc.Flags = 0 ;
541 resultantFormatDSound->BufferDesc.Control = 0 ;
542
543 pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx;
544 } else {
545 // WAVEFORMATEX or WILDCARD (WAVEFORMATEX)
546 resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
547
548 pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1);
549 }
550
551 pWaveFormatEx->nChannels = 2;
552 pWaveFormatEx->wBitsPerSample = 16; // SPDIF
553 pWaveFormatEx->cbSize = 0;
554 if (isAC3Pin) {
555 pWaveFormatEx->wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
556 pWaveFormatEx->nSamplesPerSec = 48000;
557 } else {
558 pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
559 pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE);
560 }
561 pWaveFormatEx->nBlockAlign = pWaveFormatEx->nChannels * pWaveFormatEx->wBitsPerSample / 8;
562 pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nSamplesPerSec * pWaveFormatEx->nBlockAlign;
563
564 return STATUS_SUCCESS;
565 }
566 if ((PinId == PIN_WAVE_RENDER_SINK) || (PinId == PIN_WAVE_CAPTURE_SINK)) {
567
568 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) &&
569 !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
570 return STATUS_NO_MATCH;
571 }
572
573 if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) &&
574 !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) {
575 return STATUS_NO_MATCH;
576 }
577
578 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
579 IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
580 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
581 } else
582 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
583 *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND);
584 } else {
585 return STATUS_NO_MATCH;
586 }
587
588
589 ULONG sampleRate = 0;
590 ULONG nMaxChannels = min(((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, requestedChannelCount);
591
592 // check for Vista
593 if (IoIsWdmVersionAvailable(6,0) && (PinId == PIN_WAVE_RENDER_SINK)) {
594 nMaxChannels = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels;
595 }
596 if (nMaxChannels & 0x01) {
597 nMaxChannels--;
598 }
599 if (!nMaxChannels) {
600 return STATUS_NO_MATCH;
601 }
602
603 if (isStreamRunning[PCM_OUT_STREAM]) {
604 sampleRate = stream[PCM_OUT_STREAM]->currentSampleRate;
605 } else
606 if (isStreamRunning[PCM_IN_STREAM]) {
607 sampleRate = stream[PCM_IN_STREAM]->currentSampleRate;
608 }
609 if (sampleRate == 0) {
610 if ((nMaxChannels > 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE_MULTI)) {
611 sampleRate = MAX_SAMPLE_RATE_MULTI;
612 } else
613 if ((nMaxChannels == 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE)) {
614 sampleRate = MAX_SAMPLE_RATE;
615 } else {
616 sampleRate = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency;
617 }
618 }
619
620 if ((((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency < sampleRate)
621 || (((PKSDATARANGE_AUDIO)ClientDataRange)->MinimumSampleFrequency > sampleRate)) {
622 return STATUS_NO_MATCH;
623 }
624
625 if (PinId == PIN_WAVE_RENDER_SINK) {
626 if (!OutputBufferLength) {
627 *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
628 return STATUS_BUFFER_OVERFLOW;
629 } else
630 if (OutputBufferLength < sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)) {
631 return STATUS_BUFFER_TOO_SMALL;
632 }
633
634 if (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels < 2) {
635 DBGPRINT(("[[DataRangeIntersection] mono format not supported"));
636 return STATUS_NO_MATCH;
637 }
638
639 PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1);
640 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
641 return STATUS_NOT_SUPPORTED;
642 }
643 *(PKSDATAFORMAT)ResultantFormat = *MyDataRange;
644 ((PKSDATAFORMAT)ResultantFormat)->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
645
646
647 WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
648 WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
649 WaveFormat->Format.nChannels = (WORD)nMaxChannels;
650 WaveFormat->Format.wBitsPerSample = 16;
651 WaveFormat->Format.nBlockAlign = (WaveFormat->Format.wBitsPerSample >> 3) * WaveFormat->Format.nChannels;
652 WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign;
653 WaveFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
654 WaveFormat->Format.nSamplesPerSec = sampleRate;
655 WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample;
656 switch (nMaxChannels) {
657 case 8: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; break;
658 case 6: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; break;
659 case 4: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD; break;
660 case 2: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO; break;
661 }
662 if (nMaxChannels == requestedChannelCount) {
663 WaveFormat->dwChannelMask = requestedChannelMask;
664 }
665 ((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign;
666
667 *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
668 DBGPRINT(("[DataRangeIntersection] MultiChannel Renderer: SampleRate: %d, ClientDataRange->MaxChans: %d, Channels: %d, BitPerSample: %d, BlockAlign: %d, AvgBytesPerSec: %d, ChannelMask: %08X", WaveFormat->Format.nSamplesPerSec, ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, WaveFormat->Format.nChannels, WaveFormat->Format.wBitsPerSample, WaveFormat->Format.nBlockAlign, WaveFormat->Format.nAvgBytesPerSec, WaveFormat->dwChannelMask));
669 } else
670 if (PinId == PIN_WAVE_CAPTURE_SINK) {
671 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX;
672 PWAVEFORMATEX pWaveFormatEx;
673
674 if (!OutputBufferLength) {
675 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
676 return STATUS_BUFFER_OVERFLOW;
677 } else
678 if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
679 return STATUS_BUFFER_TOO_SMALL;
680 }
681
682 if (nMaxChannels > 2) {
683 nMaxChannels = 2;
684 }
685
686 resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
687 resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength;
688 resultantFormatWFX->DataFormat.Flags = 0;
689 resultantFormatWFX->DataFormat.SampleSize = 4;
690 resultantFormatWFX->DataFormat.Reserved = 0;
691 resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
692 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_PCM);
693
694 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
695 PKSDATAFORMAT_DSOUND resultantFormatDSound;
696 resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat;
697 resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;
698 resultantFormatDSound->BufferDesc.Flags = 0 ;
699 resultantFormatDSound->BufferDesc.Control = 0 ;
700 pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx;
701 } else {
702 resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
703 pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1);
704 }
705 pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
706 pWaveFormatEx->nChannels = nMaxChannels;
707 pWaveFormatEx->nSamplesPerSec = sampleRate;
708 pWaveFormatEx->wBitsPerSample = 16;
709 pWaveFormatEx->cbSize = 0;
710 pWaveFormatEx->nBlockAlign = 4;
711 pWaveFormatEx->nAvgBytesPerSec = 192000;
712 }
713 return STATUS_SUCCESS;
714 }
715 return STATUS_NO_MATCH;
716 }
717
718 //from IMiniportWaveCyclic::NewStream()
719 #ifdef WAVERT
720 STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM *OutStream, PPORTWAVERTSTREAM OuterUnknown, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat)
721 #else
722 STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, PUNKNOWN OuterUnknown, POOL_TYPE PoolType, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat, PDMACHANNEL* OutDmaChannel, PSERVICEGROUP* OutServiceGroup)
723 #endif
724 {
725 //PAGED_CODE();
726 //ASSERT(OutStream);
727 //ASSERT(DataFormat);
728 #ifdef WAVERT
729 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream, OuterUnknown, PinID, Capture, DataFormat));
730 #else
731 //ASSERT(OutDmaChannel);
732 //ASSERT(OutServiceGroup);
733 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream, OuterUnknown, PoolType, PinID, Capture, DataFormat, OutDmaChannel, OutServiceGroup));
734 #endif
735
736 NTSTATUS ntStatus = STATUS_SUCCESS;
737 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1);
738 UInt32 streamIndex = PCM_OUT_STREAM;
739
740 ntStatus = validateFormat(DataFormat, PinID, Capture);
741 if (!NT_SUCCESS(ntStatus)) {
742 DBGPRINT(("invalid stream format"));
743 return STATUS_UNSUCCESSFUL;
744 }
745
746 CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
747
748 if (Capture) {
749 streamIndex = PCM_IN_STREAM;
750 } else if (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) {
751 streamIndex = AC3_OUT_STREAM;
752 }
753
754 // make sure the hardware is not already in use
755 if (isStreamRunning[streamIndex]) {
756 DBGPRINT(("Stream %d running, exiting...", streamIndex));
757 return STATUS_UNSUCCESSFUL;
758 }
759 if ((streamIndex == AC3_OUT_STREAM) && isStreamRunning[PCM_OUT_STREAM]) {
760 stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP_AC3);
761 }
762 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) {
763 return STATUS_UNSUCCESSFUL;
764 }
765
766 DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex,
767 waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, waveFormat->nChannels,
768 (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat))));
769
770 // the DAC and ADC can only run at the same sample rate simultaneously
771 if ((streamIndex == PCM_IN_STREAM) && isStreamRunning[PCM_OUT_STREAM]) {
772 if (waveFormat->nSamplesPerSec != stream[PCM_OUT_STREAM]->currentSampleRate) {
773 return STATUS_UNSUCCESSFUL;
774 }
775 }
776 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[PCM_IN_STREAM]) {
777 if (waveFormat->nSamplesPerSec != stream[PCM_IN_STREAM]->currentSampleRate) {
778 return STATUS_UNSUCCESSFUL;
779 }
780 }
781
782 // instantiate a stream
783 #ifdef WAVERT
784 ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, NonPagedPool);
785 #else
786 ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, PoolType);
787 #endif
788 if (!NT_SUCCESS (ntStatus)) {
789 DBGPRINT(("Failed to create stream"));
790 return ntStatus;
791 }
792
793 // initialize it
794 #ifdef WAVERT
795 ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, OuterUnknown);
796 #else
797 ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, DMAChannel[streamIndex], OutServiceGroup);
798 #endif
799 if (!NT_SUCCESS(ntStatus)) {
800 DBGPRINT(("Failed to init stream"));
801 stream[streamIndex]->Release();
802 stream[streamIndex] = NULL;
803 *OutStream = NULL;
804 #ifndef WAVERT
805 *OutServiceGroup = NULL;
806 *OutDmaChannel = NULL;
807 #endif
808 return ntStatus;
809 }
810
811 #ifdef WAVERT
812 //this has been referenced in CreateMiniportWaveStreamCMI() already
813 *OutStream = (PMINIPORTWAVERTSTREAM)stream[streamIndex];
814 #else
815 *OutDmaChannel = DMAChannel[streamIndex];
816 DMAChannel[streamIndex]->AddRef();
817 *OutStream = (PMINIPORTWAVECYCLICSTREAM)stream[streamIndex];
818 #endif
819
820 return ntStatus;
821 }
822
823 NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest)
824 {
825 //PAGED_CODE();
826 //ASSERT(PropertyRequest);
827 DBGPRINT(("[PropertyHandler_ChannelConfig]"));
828
829 #ifdef WAVERT
830 CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVERT)PropertyRequest->MajorTarget);
831 #else
832 CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVECYCLIC)PropertyRequest->MajorTarget);
833 #endif
834
835 if (PropertyRequest->Node == KSNODE_WAVE_DAC) {
836
837 if (PropertyRequest->ValueSize == 0) {
838 PropertyRequest->ValueSize = sizeof(LONG);
839 return STATUS_BUFFER_OVERFLOW;
840 } else if (PropertyRequest->ValueSize < sizeof (LONG)) {
841 PropertyRequest->ValueSize = 0;
842 return STATUS_BUFFER_TOO_SMALL;
843 }
844
845 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
846 *(PLONG)PropertyRequest->Value = that->requestedChannelMask;
847 PropertyRequest->ValueSize = sizeof(ULONG);
848 return STATUS_SUCCESS;
849 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
850 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_7POINT1) {
851 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
852 that->requestedChannelCount = 8;
853 return STATUS_SUCCESS;
854 }
855 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1) {
856 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
857 that->requestedChannelCount = 6;
858 return STATUS_SUCCESS;
859 }
860 if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) || (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND)) {
861 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
862 that->requestedChannelCount = 4;
863 return STATUS_SUCCESS;
864 }
865 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO) {
866 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
867 that->requestedChannelCount = 2;
868 return STATUS_SUCCESS;
869 }
870 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
871 PULONG AccessFlags = PULONG(PropertyRequest->Value);
872 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET;
873 PropertyRequest->ValueSize = sizeof(ULONG);
874 return STATUS_SUCCESS;
875 }
876 }
877 return STATUS_INVALID_PARAMETER;
878 }
879
880 ///////////////////////////
881
882 NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType)
883 {
884 //PAGED_CODE();
885 DBGPRINT(("CreateMiniportWaveStreamCMI"));
886
887 #ifdef WAVERT
888 *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(NULL);
889 #else
890 *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(pUnknownOuter);
891 #endif
892 if (*MiniportWaveStreamCMI) {
893 (*MiniportWaveStreamCMI)->AddRef();
894 return STATUS_SUCCESS;
895 }
896
897 return STATUS_INSUFFICIENT_RESOURCES;
898 }
899
900 NTSTATUS CMiniportWaveStreamCMI::prepareStream()
901 {
902 //PAGED_CODE();
903 DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this));
904 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber));
905
906 NTSTATUS ntStatus;
907 UInt8 reg;
908 UInt32 val;
909
910 if (state == KSSTATE_RUN) {
911 return STATUS_INVALID_DEVICE_REQUEST;
912 }
913
914 if (!(Miniport->cm)) {
915 DBGPRINT(("Miniport not set"));
916 return STATUS_INVALID_DEVICE_REQUEST;
917 }
918
919 enableSPDIF = ((currentSampleRate == 44100 || currentSampleRate == 48000 || currentSampleRate == 88200 || currentSampleRate == 96000) &&
920 ((currentResolution == 16) || (currentResolution == 24)) && (currentChannelCount == 2)) &&
921 (Miniport->cm->enableSPDIFOut);
922
923 ntStatus = setupSPDIFPlayback(enableSPDIF);
924 if (!NT_SUCCESS(ntStatus)) {
925 return ntStatus;
926 }
927
928 if (!isCaptureStream) {
929 ntStatus = setDACChannels();
930 if (!NT_SUCCESS(ntStatus)) {
931 return ntStatus;
932 }
933 }
934
935 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
936
937 val = channelNumber ? ADC_CH1 : ADC_CH0;
938 if (isCaptureStream) {
939 Miniport->cm->regFUNCTRL0 |= val; // 1->Recording
940 } else {
941 Miniport->cm->regFUNCTRL0 &= ~val; // 0->Playback
942 }
943 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
944
945 //set sampling frequency
946 val = Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1);
947 if ((currentSampleRate == 88200) || (currentSampleRate == 44100)) {
948 if (channelNumber) {
949 val &= ~SFC_CH1_MASK;
950 val |= SFC_44K_CH1;
951 } else {
952 val &= ~SFC_CH0_MASK;
953 val |= SFC_44K_CH0;
954 }
955 } else if ((currentSampleRate == 96000) || (currentSampleRate == 48000)) {
956 if (channelNumber) {
957 val &= ~SFC_CH1_MASK;
958 val |= SFC_48K_CH1;
959 } else {
960 val &= ~SFC_CH0_MASK;
961 val |= SFC_48K_CH0;
962 }
963 } else {
964 KeReleaseMutex(&Miniport->mutex, FALSE);
965 return STATUS_INVALID_DEVICE_REQUEST;
966 }
967 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL1, val);
968
969 //set resolution
970 val = Miniport->CMIAdapter->readUInt32(REG_CHFORMAT);
971 if (channelNumber) {
972 val |= FORMAT_CH1;
973 } else {
974 val |= FORMAT_CH0;
975 }
976 Miniport->CMIAdapter->writeUInt32(REG_CHFORMAT, val);
977
978 KeReleaseMutex(&Miniport->mutex, false);
979
980 return STATUS_SUCCESS;
981 }
982
983 NTSTATUS CMiniportWaveStreamCMI::setDACChannels()
984 {
985 //PAGED_CODE();
986 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this));
987 NTSTATUS ntStatus = STATUS_SUCCESS;
988
989 if (currentChannelCount > 2) {
990 if (Miniport->cm->maxChannels < currentChannelCount) {
991 return STATUS_INVALID_DEVICE_REQUEST;
992 }
993 if ((currentResolution != 16) || (currentChannelCount < 2)) {
994 return STATUS_INVALID_DEVICE_REQUEST;
995 }
996 #if OUT_CHANNEL == 0
997 return STATUS_INVALID_DEVICE_REQUEST;
998 #endif
999 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1000 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, DWORD_MAPPING);
1001 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, XCHG_DAC);
1002
1003 switch (currentChannelCount) {
1004 case 4:
1005 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
1006 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
1007 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1);
1008 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER);
1009 break;
1010 case 6:
1011 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
1012 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
1013 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1);
1014 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER);
1015 break;
1016 case 8:
1017 if (Miniport->cm->chipVersion == 68) {
1018 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
1019 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
1020 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1);
1021 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER);
1022 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1);
1023 break;
1024 } else {
1025 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1026 }
1027 default:
1028 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1029 }
1030 KeReleaseMutex(&Miniport->mutex, FALSE);
1031 } else {
1032 if (Miniport->cm->canMultiChannel) {
1033 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1034 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1 | EN_4CH_CH1);
1035 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1 | DWORD_MAPPING);
1036 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER);
1037 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, XCHG_DAC);
1038 if (Miniport->cm->chipVersion == 68) {
1039 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1);
1040 }
1041 KeReleaseMutex(&Miniport->mutex, FALSE);
1042 }
1043 }
1044 return ntStatus;
1045 }
1046
1047 NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF)
1048 {
1049 //PAGED_CODE();
1050 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF));
1051
1052 NTSTATUS ntStatus;
1053
1054 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1055
1056 if (enableSPDIF) {
1057 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDIF_OUT);
1058 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDO2DAC);
1059 #if OUT_CHANNEL == 0
1060 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0);
1061 #else
1062 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1);
1063 #endif
1064 setupAC3Passthru();
1065
1066 if ( (currentSampleRate == 48000) || (currentSampleRate == 96000) ) {
1067 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDIF_48);
1068 } else {
1069 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDIF_48);
1070 }
1071
1072 if (currentSampleRate == 96000) {
1073 #if OUT_CHANNEL == 0
1074 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1075 #else
1076 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1077 #endif
1078 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS);
1079 } else if (currentSampleRate == 88200) {
1080 #if OUT_CHANNEL == 0
1081 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH0);
1082 #else
1083 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH1);
1084 #endif
1085 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS);
1086 } else {
1087 #if OUT_CHANNEL == 0
1088 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0);
1089 #else
1090 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1);
1091 #endif
1092 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS);
1093 }
1094
1095 } else {
1096 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDIF_OUT);
1097 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDO2DAC);
1098 #if OUT_CHANNEL == 0
1099 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
1100 #else
1101 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
1102 #endif
1103 #if OUT_CHANNEL == 0
1104 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0);
1105 #else
1106 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1);
1107 #endif
1108 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS);
1109 setupAC3Passthru();
1110 }
1111
1112 KeReleaseMutex(&Miniport->mutex, false);
1113 return STATUS_SUCCESS;
1114 }
1115
1116 NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru()
1117 {
1118 //PAGED_CODE();
1119 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru()"));
1120
1121 if (enableAC3Passthru) {
1122 Miniport->CMIAdapter->writeUInt8(REG_MIXER1, Miniport->CMIAdapter->readUInt8(REG_MIXER1) | MUTE_WAVE);
1123
1124 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1);
1125 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2);
1126
1127 if (Miniport->cm->canAC3HW) {
1128 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3);
1129 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
1130 if (Miniport->cm->chipVersion >= 39) {
1131 Miniport->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
1132 }
1133 } else {
1134 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL);
1135 if (Miniport->cm->chipVersion == 33) {
1136 if (currentSampleRate >= 48000) {
1137 #if OUT_CHANNEL == 0
1138 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1139 #else
1140 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1141 #endif
1142 } else {
1143 #if OUT_CHANNEL == 0
1144 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1145 #else
1146 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1147 #endif
1148 }
1149 }
1150 }
1151 } else {
1152 Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
1153
1154 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1);
1155 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2);
1156
1157 if (Miniport->cm->canAC3HW) {
1158 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3);
1159 if (currentResolution > 16) {
1160 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL);
1161 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD24SEL);
1162 } else {
1163 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
1164 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD24SEL);
1165 }
1166 } else {
1167 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
1168 #if OUT_CHANNEL == 0
1169 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1170 #else
1171 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1172 #endif
1173 }
1174 }
1175 return STATUS_SUCCESS;
1176 }
1177
1178 CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void)
1179 {
1180 //PAGED_CODE();
1181
1182 DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI", this));
1183
1184 #ifdef WAVERT
1185 if (Port) {
1186 Port->Release();
1187 Port = NULL;
1188 }
1189 #else
1190 if (DMAChannel) {
1191 DMAChannel->Release();
1192 DMAChannel = NULL;
1193 }
1194
1195 if (ServiceGroup) {
1196 ServiceGroup->Release();
1197 ServiceGroup = NULL;
1198 }
1199 #endif
1200
1201 Miniport->isStreamRunning[streamIndex] = false;
1202
1203 if ((streamIndex == AC3_OUT_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) {
1204 KSSTATE temp = Miniport->stream[PCM_OUT_STREAM]->state;
1205 Miniport->stream[PCM_OUT_STREAM]->state = KSSTATE_STOP;
1206 Miniport->stream[PCM_OUT_STREAM]->prepareStream();
1207 Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_ACQUIRE);
1208 Miniport->stream[PCM_OUT_STREAM]->state = temp;
1209 Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_RUN_AC3);
1210 }
1211
1212 if (Miniport) {
1213 Miniport->Release();
1214 Miniport = NULL;
1215 }
1216 }
1217
1218 STDMETHODIMP CMiniportWaveStreamCMI::QueryInterface(REFIID Interface, PVOID *Object)
1219 {
1220 //PAGED_CODE();
1221 //ASSERT(Object);
1222 DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface, Object));
1223
1224 if (IsEqualGUIDAligned(Interface,IID_IUnknown)) {
1225 *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this)));
1226 #ifdef WAVERT
1227 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRTStream)) {
1228 *Object = PVOID(PMINIPORTWAVERTSTREAM(this));
1229 #else
1230 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclicStream)) {
1231 *Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this));
1232 #endif
1233 } else if (IsEqualGUIDAligned (Interface, IID_IDrmAudioStream)) {
1234 *Object = (PVOID)(PDRMAUDIOSTREAM(this));
1235 } else {
1236 *Object = NULL;
1237 }
1238
1239 if (*Object) {
1240 PUNKNOWN(*Object)->AddRef();
1241 return STATUS_SUCCESS;
1242 }
1243
1244 return STATUS_INVALID_PARAMETER;
1245 }
1246
1247 #ifdef WAVERT
1248 NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PPORTWAVERTSTREAM Port_)
1249 #else
1250 NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup)
1251 #endif
1252 {
1253 //PAGED_CODE();
1254 //ASSERT(Miniport_);
1255 //ASSERT(DataFormat);
1256
1257 NTSTATUS ntStatus;
1258
1259 #ifdef WAVERT
1260 //ASSERT(Port_);
1261 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, Port_));
1262 Port = Port_;
1263 Port->AddRef();
1264 #else
1265 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, DMAChannel_, OutServiceGroup));
1266 DMAChannel = DMAChannel_;
1267 DMAChannel->AddRef();
1268 #endif
1269
1270 Miniport = Miniport_;
1271 Miniport->AddRef();
1272
1273 streamIndex = streamIndex_;
1274 isCaptureStream = isCaptureStream_;
1275 state = KSSTATE_STOP;
1276
1277 if ( (streamIndex == PCM_OUT_STREAM) || (streamIndex == AC3_OUT_STREAM) ) {
1278 channelNumber = OUT_CHANNEL;
1279 } else {
1280 channelNumber = IN_CHANNEL;
1281 }
1282
1283 #ifndef WAVERT
1284 ntStatus = PcNewServiceGroup(&ServiceGroup,NULL);
1285 if (!NT_SUCCESS(ntStatus)) {
1286 DBGPRINT(("PcNewServiceGroup() or NewMasterDmaChannel() failed"));
1287 return ntStatus;
1288 }
1289 *OutServiceGroup = ServiceGroup;
1290 ServiceGroup->AddRef();
1291 #endif
1292
1293 ntStatus = SetFormat(DataFormat);
1294 if (!NT_SUCCESS(ntStatus)) {
1295 DBGPRINT(("SetFormat() failed"));
1296 return ntStatus;
1297 }
1298
1299 Miniport->isStreamRunning[streamIndex] = true;
1300
1301 return ntStatus;
1302 }
1303
1304 NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format)
1305 {
1306 //PAGED_CODE();
1307 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format));
1308 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1);
1309 NTSTATUS ntStatus = Miniport->validateFormat(Format, -1, isCaptureStream);
1310 if (!NT_SUCCESS(ntStatus)) {
1311 return ntStatus;
1312 }
1313 // the DAC and ADC can only run at the same sample rate simultaneously
1314 if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) {
1315 if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_OUT_STREAM]->currentSampleRate) {
1316 return STATUS_UNSUCCESSFUL;
1317 }
1318 }
1319 if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
1320 if (waveFormat->nSamplesPerSec != Miniport->stream[AC3_OUT_STREAM]->currentSampleRate) {
1321 return STATUS_UNSUCCESSFUL;
1322 }
1323 }
1324 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[PCM_IN_STREAM]) {
1325 if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_IN_STREAM]->currentSampleRate) {
1326 return STATUS_UNSUCCESSFUL;
1327 }
1328 }
1329 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
1330 return STATUS_UNSUCCESSFUL;
1331 }
1332
1333 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1334 currentSampleRate = waveFormat->nSamplesPerSec;
1335 currentChannelCount = waveFormat->nChannels;
1336 currentResolution = waveFormat->wBitsPerSample;
1337 enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat));
1338 KeReleaseMutex(&Miniport->mutex, false);
1339 ntStatus = prepareStream();
1340
1341 return ntStatus;
1342 }
1343
1344 // DRM crap - we're supposed to disable every digital interface here
1345 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::SetContentId(ULONG contentId, PCDRMRIGHTS drmRights)
1346 {
1347 //PAGED_CODE();
1348 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId, drmRights));
1349
1350 return STATUS_SUCCESS;
1351 }
1352
1353 #ifdef WAVERT
1354
1355 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, PMDL *userModeBuffer, ULONG *bufferSize, ULONG *bufferOffset, MEMORY_CACHING_TYPE *cacheType)
1356 {
1357 //PAGED_CODE();
1358
1359 PHYSICAL_ADDRESS low;
1360 PHYSICAL_ADDRESS high;
1361 DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType));
1362
1363 if (size <= size % (currentChannelCount * 2)) {
1364 return STATUS_UNSUCCESSFUL;
1365 }
1366 size -= size % (currentChannelCount * 2);
1367
1368 if (size == 0) {
1369 return STATUS_UNSUCCESSFUL;
1370 }
1371
1372 low.QuadPart = 0;
1373 high.HighPart = 0, high.LowPart = MAXULONG;
1374
1375 audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size);
1376
1377 if (!audioBufferMDL) {
1378 DBGPRINT(("AllocateContiguousPagesForMdl() failed"));
1379 return STATUS_UNSUCCESSFUL;
1380 }
1381
1382 dmaAddress = Port->GetPhysicalPageAddress(audioBufferMDL, 0).LowPart;
1383 dmaMemorySize = size;
1384
1385 *userModeBuffer = audioBufferMDL;
1386 *bufferSize = size;
1387 *bufferOffset = 0;
1388 *cacheType = MmCached;
1389
1390 return STATUS_SUCCESS;
1391 }
1392
1393
1394 STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size)
1395 {
1396 //PAGED_CODE();
1397 DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size));
1398
1399 Port->FreePagesFromMdl(Mdl);
1400 audioBufferMDL = NULL;
1401 dmaAddress = 0;
1402 dmaMemorySize = 0;
1403 }
1404
1405 STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency) {
1406 //PAGED_CODE();
1407 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency));
1408 hwLatency->FifoSize = 32;
1409 hwLatency->ChipsetDelay = 0;
1410 hwLatency->CodecDelay = 4;
1411 }
1412
1413 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister)
1414 {
1415 //PAGED_CODE();
1416 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister));
1417
1418 return STATUS_UNSUCCESSFUL;
1419 }
1420
1421 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister)
1422 {
1423 //PAGED_CODE();
1424 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister));
1425
1426 return STATUS_UNSUCCESSFUL;
1427 }
1428
1429 #endif // WAVERT
1430
1431 /*
1432 ** non-paged code below
1433 */
1434 #pragma code_seg()
1435
1436 STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState)
1437 {
1438 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d)", this, NewState));
1439
1440 UInt32 inthld, chen, reset, pause;
1441 UInt8 reg;
1442
1443 inthld = EN_CH0_INT << channelNumber;
1444 chen = EN_CH0 << channelNumber;
1445 reset = RST_CH0 << channelNumber;
1446 pause = PAUSE_CH0 << channelNumber;
1447
1448 NTSTATUS ntStatus = STATUS_SUCCESS;
1449
1450 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
1451 return STATUS_INVALID_PARAMETER;
1452 }
1453
1454 if (NewState == KSSTATE_RUN_AC3) {
1455 NewState = state;
1456 state = KSSTATE_STOP;
1457 }
1458
1459 // STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP
1460 if (state != NewState) {
1461 switch (NewState) {
1462 case KSSTATE_ACQUIRE:
1463 DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state));
1464 if (state == KSSTATE_PAUSE) {
1465 break;
1466 }
1467
1468 #ifdef WAVERT
1469 if ((dmaMemorySize == 0) || (dmaAddress == 0)) {
1470 return STATUS_UNSUCCESSFUL;
1471 }
1472 dmaSize = (dmaMemorySize / (2 * (currentResolution >> 3)) );
1473 periodSize = dmaSize;
1474 DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress, dmaMemorySize, dmaSize));
1475 #else
1476 if (currentResolution == 24) {
1477 dmaSize = (DMAChannel->BufferSize() / (2 * (24 >> 3)) );
1478 } else {
1479 dmaSize = (DMAChannel->BufferSize() / (2 * (currentResolution >> 3)) );
1480 }
1481 #endif
1482 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber));
1483 DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate, currentResolution, currentChannelCount));
1484
1485 if (periodSize > dmaSize) {
1486 periodSize = dmaSize;
1487 }
1488
1489 // set address of the DMA buffer
1490 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1491 reg = channelNumber ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
1492 #ifdef WAVERT
1493 Miniport->CMIAdapter->writeUInt32(reg, dmaAddress);
1494 #else
1495 Miniport->CMIAdapter->writeUInt32(reg, DMAChannel->PhysicalAddress().u.LowPart);
1496 #endif
1497 // count of samples
1498 reg = channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2;
1499 Miniport->CMIAdapter->writeUInt16(reg, dmaSize-1);
1500 Miniport->CMIAdapter->writeUInt16(reg + 2, periodSize-1);
1501 DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize, periodSize, Miniport->cm->enableSPDIFIn));
1502 if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) {
1503 #if OUT_CHANNEL==0
1504 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1);
1505 #else
1506 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0);
1507 #endif
1508 }
1509 KeReleaseMutex(&Miniport->mutex, false);
1510 break;
1511
1512 case KSSTATE_PAUSE:
1513 DBGPRINT(("---KSSTATE_PAUSE: previous state: %d", state));
1514 if (state == KSSTATE_RUN) {
1515 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1516 Miniport->cm->regFUNCTRL0 |= pause;
1517 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
1518 KeReleaseMutex(&Miniport->mutex, FALSE);
1519 }
1520 if (state == KSSTATE_STOP) {
1521 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1522 Miniport->cm->regFUNCTRL0 &= ~pause;
1523 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
1524 KeReleaseMutex(&Miniport->mutex, false);
1525 }
1526 break;
1527
1528 case KSSTATE_RUN:
1529 DBGPRINT(("---KSSTATE_RUN: previous state: %d", state));
1530
1531 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1532 // set interrupt
1533 Miniport->CMIAdapter->setUInt32Bit(REG_INTHLDCLR, inthld);
1534 Miniport->cm->regFUNCTRL0 &= ~pause;
1535 Miniport->cm->regFUNCTRL0 |= chen;
1536 // and enable the channel
1537 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
1538
1539 DBGPRINT(("---FUNCTRL0: 0x%08X", Miniport->cm->regFUNCTRL0));
1540 DBGPRINT(("---FUNCTRL1: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1)));
1541 DBGPRINT(("---CHFORMAT: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_CHFORMAT)));
1542 DBGPRINT(("---LEGACYCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_LEGACY)));
1543 DBGPRINT(("---MISCCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_MISCCTRL)));
1544 DBGPRINT(("---MIX1: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER1)));
1545 DBGPRINT(("---MIX2: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER2)));
1546 DBGPRINT(("---MIX3: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER3)));
1547
1548 KeReleaseMutex(&Miniport->mutex, false);
1549 break;
1550
1551 case KSSTATE_STOP_AC3:
1552 case KSSTATE_STOP:
1553 DBGPRINT(("---KSSTATE_STOP: previous state: %d", state));
1554 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1555 // clear interrupt
1556 Miniport->CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, inthld);
1557 Miniport->cm->regFUNCTRL0 &= ~chen;
1558 // reset
1559 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 | reset);
1560 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 & ~reset);
1561 if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) {
1562 #if OUT_CHANNEL==0
1563 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
1564 #else
1565 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
1566 #endif
1567 }
1568 KeReleaseMutex(&Miniport->mutex, FALSE);
1569 break;
1570 }
1571 if (NewState != KSSTATE_STOP_AC3) {
1572 state = NewState;
1573 }
1574 }
1575 return ntStatus;
1576 }
1577
1578 #ifdef WAVERT
1579 STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position)
1580 {
1581 //ASSERT(Position);
1582
1583 UInt32 reg;
1584
1585 if ((state == KSSTATE_RUN) && (dmaAddress)) {
1586 reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
1587 Position->PlayOffset = Miniport->CMIAdapter->readUInt32(reg) - dmaAddress;
1588 Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8;
1589 } else {
1590 Position->PlayOffset = 0;
1591 Position->WriteOffset = 0;
1592 }
1593
1594 return STATUS_SUCCESS;
1595 }
1596
1597 #else //WaveCyclic
1598 STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PULONG Position)
1599 {
1600 //ASSERT(Position);
1601
1602 UInt32 reg;
1603
1604 if ((DMAChannel) && (state == KSSTATE_RUN)) {
1605 #if 0
1606 // this implementation messes with SPDIF-in recording
1607 reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2;
1608 *Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1);
1609 *Position *= 2 * (currentResolution >> 3);
1610 #else
1611 reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
1612 *Position = Miniport->CMIAdapter->readUInt32(reg);
1613 if (*Position > DMAChannel->PhysicalAddress().u.LowPart) {
1614 *Position -= DMAChannel->PhysicalAddress().u.LowPart;
1615 } else {
1616 *Position = 0;
1617 }
1618 #endif
1619 } else {
1620 *Position = 0;
1621 }
1622
1623 return STATUS_SUCCESS;
1624 }
1625
1626 STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, PULONG FramingSize)
1627 {
1628 Miniport->notificationInterval = Interval;
1629
1630 if (state == KSSTATE_RUN) {
1631 return 0;
1632 }
1633 periodSize = Interval * currentSampleRate/1000;
1634 *FramingSize = periodSize*currentChannelCount*(currentResolution >> 3);
1635
1636 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1637 Miniport->CMIAdapter->writeUInt16((channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2) + 2, periodSize-1);
1638 KeReleaseMutex(&Miniport->mutex, FALSE);
1639
1640 DBGPRINT(("periodSize: %x, FramingSize: %x", periodSize, *FramingSize));
1641 return Interval;
1642 }
1643
1644 STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(OUT PLONGLONG PhysicalPosition)
1645 {
1646 *PhysicalPosition = (_100NS_UNITS_PER_SECOND / currentChannelCount * (currentResolution >> 3) * *PhysicalPosition) / currentSampleRate;
1647 return STATUS_SUCCESS;
1648 }
1649
1650
1651 STDMETHODIMP_(void) CMiniportWaveStreamCMI::Silence(PVOID Buffer, ULONG ByteCount)
1652 {
1653 RtlFillMemory(Buffer, ByteCount, 0x00);
1654 }
1655
1656 #endif //WAVERT
1657
1658 STDMETHODIMP_(void) CMiniportWaveCMI::ServiceWaveISR(UInt32 streamIndex)
1659 {
1660 #ifndef WAVERT
1661 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) {
1662 streamIndex = AC3_OUT_STREAM;
1663 }
1664 if (Port && stream[streamIndex]->ServiceGroup) {
1665 Port->Notify(stream[streamIndex]->ServiceGroup);
1666 }
1667 #endif
1668 }