Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencommon.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (c) 2006-2007 dogbert <dogber1@gmail.com> 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions 00007 are met: 00008 1. Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 2. Redistributions in binary form must reproduce the above copyright 00011 notice, this list of conditions and the following disclaimer in the 00012 documentation and/or other materials provided with the distribution. 00013 3. The name of the author may not be used to endorse or promote products 00014 derived from this software without specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "common.hpp" 00029 00030 #ifdef _MSC_VER 00031 #pragma code_seg("PAGE") /* warning - ignored by GCC compiler */ 00032 #endif 00033 00034 NTSTATUS 00035 NewCMIAdapter( 00036 PUNKNOWN *Unknown, 00037 REFCLSID, 00038 PUNKNOWN UnknownOuter, 00039 POOL_TYPE PoolType) 00040 { 00041 #if 1 00042 //PAGED_CODE(); 00043 DBGPRINT(("NewCMIAdapter()")); 00044 ASSERT (Unknown); 00045 #endif 00046 STD_CREATE_BODY_(CCMIAdapter, Unknown, UnknownOuter, PoolType, PCMIADAPTER); 00047 } 00048 00049 00050 STDMETHODIMP_(NTSTATUS) CCMIAdapter::init(PRESOURCELIST ResourceList, PDEVICE_OBJECT aDeviceObject) 00051 { 00052 #if 0 00053 //PAGED_CODE(); 00054 //ASSERT(ResourceList); 00055 //ASSERT(aDeviceObject); 00056 //ASSERT(ResourceList->FindTranslatedPort(0)); 00057 DBGPRINT(("CCMIAdapter[%p]::init()", this)); 00058 #endif 00059 00060 NTSTATUS ntStatus = STATUS_SUCCESS; 00061 00062 RtlFillMemory(&mixerCache, 0xFF, 0xFF); 00063 RtlFillMemory(&cm, sizeof(cm), 0x00); 00064 00065 DeviceObject = aDeviceObject; 00066 00067 cm.IOBase = 0; 00068 for ( UINT i=0; i < ResourceList->NumberOfPorts(); i++ ) { 00069 if (ResourceList->FindTranslatedPort(i)->u.Port.Length == 0x100) { 00070 cm.IOBase = (UInt32*)ResourceList->FindTranslatedPort(i)->u.Port.Start.QuadPart; 00071 } 00072 } 00073 00074 if (cm.IOBase == 0) { 00075 return STATUS_INSUFFICIENT_RESOURCES; 00076 } 00077 cm.MPUBase = 0; 00078 00079 #ifdef WAVERT 00080 INFOPRINT(("Driver Version: %s-WAVERT", CMIVERSION)); 00081 #else 00082 INFOPRINT(("Driver Version: %s", CMIVERSION)); 00083 #endif 00084 INFOPRINT(("Configuration:")); 00085 INFOPRINT((" IO Base: 0x%X", cm.IOBase)); 00086 INFOPRINT((" MPU Base: 0x%X", cm.MPUBase)); 00087 00088 if (!queryChip()) { 00089 return STATUS_INSUFFICIENT_RESOURCES; 00090 } 00091 00092 INFOPRINT((" Chip Version: %d", cm.chipVersion)); 00093 INFOPRINT((" Max Channels: %d", cm.maxChannels)); 00094 INFOPRINT((" CanAC3HW: %d", cm.canAC3HW)); 00095 00096 resetController(); 00097 00098 ntStatus = PcNewInterruptSync(&(InterruptSync), NULL, ResourceList, 0, InterruptSyncModeNormal); 00099 if (!NT_SUCCESS(ntStatus) || !(InterruptSync)) { 00100 DBGPRINT(("Failed to create an interrupt sync!")); 00101 return STATUS_INSUFFICIENT_RESOURCES; 00102 } 00103 ntStatus = InterruptSync->RegisterServiceRoutine(InterruptServiceRoutine, (PVOID)this, FALSE); 00104 if (!NT_SUCCESS(ntStatus)) { 00105 DBGPRINT(("Failed to register ISR!")); 00106 return ntStatus; 00107 } 00108 00109 ntStatus = InterruptSync->Connect(); 00110 if (!NT_SUCCESS(ntStatus)) { 00111 DBGPRINT(("Failed to connect the ISR with InterruptSync!")); 00112 return ntStatus; 00113 } 00114 00115 // Initialize the device state. 00116 CurrentPowerState = PowerDeviceD0; 00117 00118 return ntStatus; 00119 } 00120 00121 00122 CCMIAdapter::~CCMIAdapter() 00123 { 00124 //PAGED_CODE (); 00125 DBGPRINT(("CCMIAdapter[%p]::~CCMIAdapter()", this)); 00126 00127 if (InterruptSync) { 00128 InterruptSync->Disconnect(); 00129 InterruptSync->Release(); 00130 InterruptSync = NULL; 00131 } 00132 } 00133 00134 STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryInterface(REFIID Interface, PVOID* Object) 00135 { 00136 //PAGED_CODE(); 00137 00138 DBGPRINT(("CCMIAdapter[%p]::NonDelegatingQueryInterface()", this)); 00139 00140 //ASSERT(Object); 00141 00142 // Is it IID_IUnknown? 00143 if (IsEqualGUIDAligned (Interface, IID_IUnknown)) { 00144 *Object = (PVOID)(PUNKNOWN)(PCMIADAPTER)this; 00145 } 00146 else 00147 // or IID_IAdapterCommon ... 00148 if (IsEqualGUIDAligned (Interface, IID_ICMIAdapter)) { 00149 *Object = (PVOID)(PCMIADAPTER)this; 00150 } else 00151 // or IID_IAdapterPowerManagement ... 00152 if (IsEqualGUIDAligned (Interface, IID_IAdapterPowerManagement)) { 00153 *Object = (PVOID)(PADAPTERPOWERMANAGEMENT)this; 00154 } else { 00155 // nothing found, must be an unknown interface. 00156 *Object = NULL; 00157 return STATUS_INVALID_PARAMETER; 00158 } 00159 00160 // 00161 // We reference the interface for the caller. 00162 // 00163 ((PUNKNOWN)*Object)->AddRef(); 00164 return STATUS_SUCCESS; 00165 } 00166 00167 bool CCMIAdapter::queryChip() 00168 { 00169 //PAGED_CODE(); 00170 DBGPRINT(("CCMIAdapter[%p]::queryChip()", this)); 00171 00172 UInt32 version = readUInt32(REG_INTHLDCLR) & VERSION_MASK; 00173 if (version == 0xFFFFFFFF) { 00174 return false; 00175 } 00176 if (version) { 00177 if (version & VERSION_68) { 00178 cm.chipVersion = 68; 00179 cm.maxChannels = 8; 00180 cm.canAC3HW = true; 00181 cm.hasDualDAC = true; 00182 cm.canMultiChannel = true; 00183 return true; 00184 } 00185 if (version & VERSION_55) { 00186 cm.chipVersion = 55; 00187 cm.maxChannels = 6; 00188 cm.canAC3HW = true; 00189 cm.hasDualDAC = true; 00190 cm.canMultiChannel = true; 00191 return true; 00192 } 00193 if (version & VERSION_39) { 00194 cm.chipVersion = 39; 00195 if (version & VERSION_39_6) { 00196 cm.maxChannels = 6; 00197 } else { 00198 cm.maxChannels = 4; 00199 } 00200 cm.canAC3HW = true; 00201 cm.hasDualDAC = true; 00202 cm.canMultiChannel = true; 00203 return true; 00204 } 00205 } else { 00206 version = readUInt32(REG_CHFORMAT) & VERSION_37; 00207 if (!version) { 00208 cm.chipVersion = 33; 00209 cm.maxChannels = 2; 00210 if (cm.doAC3SW) { 00211 cm.canAC3SW = true; 00212 } else { 00213 cm.canAC3HW = true; 00214 } 00215 cm.hasDualDAC = true; 00216 return true; 00217 } else { 00218 cm.chipVersion = 37; 00219 cm.maxChannels = 2; 00220 cm.canAC3HW = true; 00221 cm.hasDualDAC = 1; 00222 return true; 00223 } 00224 } 00225 return false; 00226 } 00227 00228 void CCMIAdapter::resetMixer() 00229 { 00230 //PAGED_CODE(); 00231 DBGPRINT(("CCMIAdapter[%p]::resetMixer()", this)); 00232 00233 writeMixer(0, 0); 00234 setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); 00235 } 00236 00237 void CCMIAdapter::resetController() 00238 { 00239 #if 0 00240 //PAGED_CODE(); 00241 DBGPRINT(("CCMIAdapter[%p]::resetController()", this)); 00242 #endif 00243 00244 writeUInt32(REG_INTHLDCLR, 0); 00245 00246 #if OUT_CHANNEL == 1 00247 writeUInt32(REG_FUNCTRL0, ADC_CH0 | (RST_CH0 | RST_CH1)); 00248 writeUInt32(REG_FUNCTRL0, ADC_CH0 & ~(RST_CH0 | RST_CH1)); 00249 #else 00250 writeUInt32(REG_FUNCTRL0, ADC_CH1 | (RST_CH0 | RST_CH1)); 00251 writeUInt32(REG_FUNCTRL0, ADC_CH1 & ~(RST_CH0 | RST_CH1)); 00252 #endif 00253 KeStallExecutionProcessor(100L); 00254 00255 writeUInt32(REG_FUNCTRL0, 0); 00256 writeUInt32(REG_FUNCTRL1, 0); 00257 00258 writeUInt32(REG_CHFORMAT, 0); 00259 writeUInt32(REG_MISCCTRL, EN_DBLDAC); 00260 #if OUT_CHANNEL == 1 00261 setUInt32Bit(REG_MISCCTRL, XCHG_DAC); 00262 #endif 00263 00264 setUInt32Bit(REG_FUNCTRL1, BREQ); 00265 00266 writeMixer(0, 0); 00267 00268 return; 00269 } 00270 00271 00272 STDMETHODIMP_(NTSTATUS) CCMIAdapter::activateMPU(ULONG* MPUBase) 00273 { 00274 UInt32 LegacyCtrl; 00275 #if 0 00276 //PAGED_CODE(); 00277 DBGPRINT(("CCMIAdapter[%p]::activateMPU(%X)", this, MPUBase)); 00278 #endif 00279 00280 switch ((LONGLONG)MPUBase) { 00281 case 0x300: LegacyCtrl = UART_300; break; 00282 case 0x310: LegacyCtrl = UART_310; break; 00283 case 0x320: LegacyCtrl = UART_320; break; 00284 case 0x330: LegacyCtrl = UART_330; break; // UART_330 == 0 00285 default: LegacyCtrl = 0xFFFFFFFF; break; 00286 } 00287 if (LegacyCtrl < 0xFFFFFFFF) { 00288 cm.MPUBase = MPUBase; 00289 setUInt32Bit(REG_FUNCTRL1, EN_UART); 00290 writeUInt32(REG_LEGACY, LegacyCtrl); 00291 return STATUS_SUCCESS; 00292 } 00293 00294 return STATUS_UNSUCCESSFUL; 00295 } 00296 00297 // "The code for this method must reside in paged memory.", IID_IAdapterPowerManagement.PowerChangeState() docs 00298 // XP's order of power states when going to hibernate: D3 -> D0, waking up: D0 -> D3. 00299 STDMETHODIMP_(void) CCMIAdapter::PowerChangeState(POWER_STATE NewState) 00300 { 00301 #if 0 00302 //PAGED_CODE(); 00303 DBGPRINT(("CCMIAdapter[%p]::PowerChangeState(%p)", this, NewState)); 00304 #endif 00305 00306 if (NewState.DeviceState == CurrentPowerState ) { 00307 return; 00308 } 00309 00310 switch (NewState.DeviceState) { 00311 case PowerDeviceD0: // powering up, hardware access allowed 00312 clearUInt32Bit(REG_MISCCTRL, PWD_CHIP); 00313 cm.WaveMiniport->powerUp(); 00314 CurrentPowerState = NewState.DeviceState; 00315 break; 00316 00317 case PowerDeviceD1: // powering down, hardware access still allowed 00318 setUInt32Bit(REG_MISCCTRL, PWD_CHIP); 00319 CurrentPowerState = NewState.DeviceState; 00320 break; 00321 00322 case PowerDeviceD2: // sleep state - hardware access not allowed 00323 case PowerDeviceD3: // hibernation state - hardware access not allowed 00324 if (CurrentPowerState == PowerDeviceD0) { 00325 cm.WaveMiniport->powerDown(); 00326 setUInt32Bit(REG_MISCCTRL, PWD_CHIP); 00327 } 00328 CurrentPowerState = NewState.DeviceState; 00329 break; 00330 default: // unknown power state 00331 break; 00332 } 00333 } 00334 00335 STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryPowerChangeState(POWER_STATE NewStateQuery) 00336 { 00337 #if 0 00338 //PAGED_CODE(); 00339 DBGPRINT(("CCMIAdapter[%p]::QueryPowerChangeState(%p)", this, NewStateQuery)); 00340 #endif 00341 return STATUS_SUCCESS; 00342 } 00343 00344 STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryDeviceCapabilities(PDEVICE_CAPABILITIES PowerDeviceCaps) 00345 { 00346 #if 0 00347 //PAGED_CODE(); 00348 DBGPRINT(("CCMIAdapter[%p]::QueryDeviceCapabilities(%p)", this, PowerDeviceCaps)); 00349 #endif 00350 return STATUS_SUCCESS; 00351 } 00352 00353 STDMETHODIMP_(NTSTATUS) CCMIAdapter::loadSBMixerFromMemory() 00354 { 00355 UInt8 sbIndex[] = { 0x04, 0x0A, 0x22, 0x28, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x36, 0x37, 0x38, 00356 0x39, 0x3A, 0x3C, 0x3D, 0x3E, 0xF0 }; 00357 00358 #if 0 00359 //PAGED_CODE(); 00360 DBGPRINT(("CCMIAdapter[%p]::loadSBMixerFromMemory()", this)); 00361 #endif 00362 for ( UINT i = 0; i < (sizeof(sbIndex)/sizeof(sbIndex[0])); i++ ) { 00363 writeUInt8(REG_SBINDEX, sbIndex[i]); 00364 writeUInt8(REG_SBDATA, mixerCache[i]); 00365 } 00366 00367 return STATUS_SUCCESS; 00368 } 00369 00370 /* 00371 ** non-paged code below 00372 */ 00373 #ifdef _MSC_VER 00374 #pragma code_seg() /* warning - ignored by GCC compiler */ 00375 #endif 00376 00377 STDMETHODIMP_(UInt8) CCMIAdapter::readUInt8(UInt8 reg) 00378 { 00379 return READ_PORT_UCHAR((PUCHAR)(reinterpret_cast<PUCHAR>(cm.IOBase) + reg)); 00380 } 00381 00382 STDMETHODIMP_(void) CCMIAdapter::writeUInt8(UInt8 cmd, UInt8 value) 00383 { 00384 WRITE_PORT_UCHAR((PUCHAR)(reinterpret_cast<PUCHAR>(cm.IOBase) + cmd), value); 00385 } 00386 00387 STDMETHODIMP_(void) CCMIAdapter::setUInt8Bit(UInt8 reg, UInt8 flag) 00388 { 00389 writeUInt8(reg, readUInt8(reg) | flag); 00390 } 00391 00392 STDMETHODIMP_(void) CCMIAdapter::clearUInt8Bit(UInt8 reg, UInt8 flag) 00393 { 00394 writeUInt8(reg, readUInt8(reg) & ~flag); 00395 } 00396 00397 STDMETHODIMP_(UInt16) CCMIAdapter::readUInt16(UInt8 reg) 00398 { 00399 return READ_PORT_USHORT((PUSHORT)(reinterpret_cast<PUCHAR>(cm.IOBase) + reg)); 00400 } 00401 00402 STDMETHODIMP_(void) CCMIAdapter::writeUInt16(UInt8 cmd, UInt16 value) 00403 { 00404 WRITE_PORT_USHORT((PUSHORT)(reinterpret_cast<PUCHAR>(cm.IOBase) + cmd), value); 00405 } 00406 00407 00408 STDMETHODIMP_(UInt32) CCMIAdapter::readUInt32(UInt8 reg) 00409 { 00410 return READ_PORT_ULONG((PULONG)(reinterpret_cast<PUCHAR>(cm.IOBase) + reg)); 00411 } 00412 00413 STDMETHODIMP_(void) CCMIAdapter::writeUInt32(UInt8 cmd, UInt32 value) 00414 { 00415 WRITE_PORT_ULONG((PULONG)(reinterpret_cast<PUCHAR>(cm.IOBase) + cmd), value); 00416 } 00417 00418 STDMETHODIMP_(void) CCMIAdapter::setUInt32Bit(UInt8 reg, UInt32 flag) 00419 { 00420 writeUInt32(reg, readUInt32(reg) | flag); 00421 } 00422 00423 STDMETHODIMP_(void) CCMIAdapter::clearUInt32Bit(UInt8 reg, UInt32 flag) 00424 { 00425 writeUInt32(reg, readUInt32(reg) & ~flag); 00426 } 00427 00428 STDMETHODIMP_(UInt8) CCMIAdapter::readMixer(UInt8 index) 00429 { 00430 if (mixerCache[index] == 0xFF) { 00431 writeUInt8(REG_SBINDEX, index); 00432 mixerCache[index] = readUInt8(REG_SBDATA); 00433 } 00434 return mixerCache[index]; 00435 } 00436 00437 STDMETHODIMP_(void) CCMIAdapter::writeMixer(UInt8 index, UInt8 value) 00438 { 00439 if (value != mixerCache[index]) { 00440 mixerCache[index] = value; 00441 writeUInt8(REG_SBINDEX, index); 00442 writeUInt8(REG_SBDATA, value); 00443 } 00444 } 00445 00446 STDMETHODIMP_(void) CCMIAdapter::setMixerBit(UInt8 index, UInt8 flag) 00447 { 00448 writeMixer(index, readMixer(index) | flag); 00449 } 00450 00451 STDMETHODIMP_(void) CCMIAdapter::clearMixerBit(UInt8 index, UInt8 flag) 00452 { 00453 writeMixer(index, readMixer(index) & ~flag); 00454 } 00455 00456 NTSTATUS NTAPI CCMIAdapter::InterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID DynamicContext) 00457 { 00458 UInt32 status, mask = 0; 00459 00460 CCMIAdapter *CMIAdapter = (CCMIAdapter *)DynamicContext; 00461 00462 #if 0 00463 //ASSERT(InterruptSync); 00464 //ASSERT(DynamicContext); 00465 #endif 00466 00467 if (!(CMIAdapter->cm.WaveMiniport)) { 00468 return STATUS_UNSUCCESSFUL; 00469 } 00470 00471 status = CMIAdapter->readUInt32(REG_INT_STAT); 00472 00473 if ((!(status & INT_PENDING)) || (status == 0xFFFFFFFF)) { 00474 return STATUS_UNSUCCESSFUL; 00475 } 00476 00477 if (status & INT_CH0) { 00478 mask |= EN_CH0_INT; 00479 #if OUT_CHANNEL == 0 00480 CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_OUT_STREAM); 00481 #endif 00482 #if IN_CHANNEL == 0 00483 CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_IN_STREAM); 00484 #endif 00485 } 00486 if (status & INT_CH1) { 00487 mask |= EN_CH1_INT; 00488 #if OUT_CHANNEL == 1 00489 CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_OUT_STREAM); 00490 #endif 00491 #if IN_CHANNEL == 1 00492 CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_IN_STREAM); 00493 #endif 00494 } 00495 #ifdef UART 00496 if (status & INT_UART) { 00497 // the UART miniport should catch / have caught the interrupt 00498 return STATUS_UNSUCCESSFUL; 00499 } 00500 #endif 00501 00502 CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, mask); 00503 CMIAdapter->setUInt32Bit(REG_INTHLDCLR, mask); 00504 00505 return STATUS_SUCCESS; 00506 } Generated on Sun May 27 2012 04:28:38 for ReactOS by
1.7.6.1
|