Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendma_slave.cpp
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/wdm/audio/backpln/portcls/dma_init.c 00005 * PURPOSE: portcls dma support object 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 #include "private.hpp" 00010 00011 class CDmaChannelInit : public IDmaChannelInit 00012 { 00013 public: 00014 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 00015 00016 STDMETHODIMP_(ULONG) AddRef() 00017 { 00018 InterlockedIncrement(&m_Ref); 00019 return m_Ref; 00020 } 00021 STDMETHODIMP_(ULONG) Release() 00022 { 00023 InterlockedDecrement(&m_Ref); 00024 00025 if (!m_Ref) 00026 { 00027 delete this; 00028 return 0; 00029 } 00030 return m_Ref; 00031 } 00032 IMP_IDmaChannelInit; 00033 CDmaChannelInit(IUnknown * OuterUnknown){} 00034 virtual ~CDmaChannelInit(){} 00035 00036 protected: 00037 00038 PDEVICE_OBJECT m_pDeviceObject; 00039 PDMA_ADAPTER m_pAdapter; 00040 00041 BOOL m_DmaStarted; 00042 00043 ULONG m_MapSize; 00044 PVOID m_MapRegisterBase; 00045 00046 ULONG m_LastTransferCount; 00047 00048 ULONG m_MaximumBufferSize; 00049 ULONG m_MaxMapRegisters; 00050 ULONG m_AllocatedBufferSize; 00051 ULONG m_BufferSize; 00052 00053 PHYSICAL_ADDRESS m_Address; 00054 PVOID m_Buffer; 00055 PMDL m_Mdl; 00056 BOOLEAN m_WriteToDevice; 00057 00058 friend IO_ALLOCATION_ACTION NTAPI AdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context); 00059 00060 LONG m_Ref; 00061 }; 00062 00063 00064 00065 //--------------------------------------------------------------- 00066 // IUnknown methods 00067 // 00068 00069 extern GUID IID_IDmaChannelSlave; 00070 00071 NTSTATUS 00072 NTAPI 00073 CDmaChannelInit::QueryInterface( 00074 IN REFIID refiid, 00075 OUT PVOID* Output) 00076 { 00077 if (IsEqualGUIDAligned(refiid, IID_IUnknown) || 00078 IsEqualGUIDAligned(refiid, IID_IDmaChannel)) 00079 //IsEqualGUIDAligned(refiid, IID_IDmaChannelSlave)) // HACK 00080 { 00081 *Output = PVOID(PUNKNOWN(this)); 00082 PUNKNOWN(*Output)->AddRef(); 00083 return STATUS_SUCCESS; 00084 } 00085 DPRINT("No interface!!!\n"); 00086 return STATUS_UNSUCCESSFUL; 00087 } 00088 00089 //--------------------------------------------------------------- 00090 // IDmaChannel methods 00091 // 00092 00093 NTSTATUS 00094 NTAPI 00095 CDmaChannelInit::AllocateBuffer( 00096 IN ULONG BufferSize, 00097 IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL) 00098 { 00099 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00100 00101 // Did the caller already allocate a buffer ?*/ 00102 if (m_Buffer) 00103 { 00104 DPRINT("CDmaChannelInit_AllocateBuffer free common buffer first \n"); 00105 return STATUS_UNSUCCESSFUL; 00106 } 00107 00108 m_Buffer = m_pAdapter->DmaOperations->AllocateCommonBuffer(m_pAdapter, BufferSize, &m_Address, FALSE); 00109 if (!m_Buffer) 00110 { 00111 DPRINT("CDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n"); 00112 return STATUS_UNSUCCESSFUL; 00113 } 00114 00115 m_BufferSize = BufferSize; 00116 m_AllocatedBufferSize = BufferSize; 00117 DPRINT("CDmaChannelInit::AllocateBuffer Success Buffer %p BufferSize %u Address %x\n", m_Buffer, BufferSize, m_Address); 00118 00119 return STATUS_SUCCESS; 00120 } 00121 00122 ULONG 00123 NTAPI 00124 CDmaChannelInit::AllocatedBufferSize() 00125 { 00126 DPRINT("CDmaChannelInit_AllocatedBufferSize: this %p BufferSize %u\n", this, m_BufferSize); 00127 return m_AllocatedBufferSize; 00128 } 00129 00130 VOID 00131 NTAPI 00132 CDmaChannelInit::CopyFrom( 00133 IN PVOID Destination, 00134 IN PVOID Source, 00135 IN ULONG ByteCount 00136 ) 00137 { 00138 DPRINT("CDmaChannelInit_CopyFrom: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount); 00139 00140 CopyTo(Destination, Source, ByteCount); 00141 } 00142 00143 VOID 00144 NTAPI 00145 CDmaChannelInit::CopyTo( 00146 IN PVOID Destination, 00147 IN PVOID Source, 00148 IN ULONG ByteCount 00149 ) 00150 { 00151 DPRINT("CDmaChannelInit_CopyTo: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount); 00152 RtlCopyMemory(Destination, Source, ByteCount); 00153 } 00154 00155 VOID 00156 NTAPI 00157 CDmaChannelInit::FreeBuffer() 00158 { 00159 DPRINT("CDmaChannelInit_FreeBuffer: this %p\n", this); 00160 00161 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00162 00163 if (!m_Buffer) 00164 { 00165 DPRINT("CDmaChannelInit_FreeBuffer allocate common buffer first \n"); 00166 return; 00167 } 00168 00169 m_pAdapter->DmaOperations->FreeCommonBuffer(m_pAdapter, m_AllocatedBufferSize, m_Address, m_Buffer, FALSE); 00170 m_Buffer = NULL; 00171 m_AllocatedBufferSize = 0; 00172 m_Address.QuadPart = 0LL; 00173 00174 if (m_Mdl) 00175 { 00176 IoFreeMdl(m_Mdl); 00177 m_Mdl = NULL; 00178 } 00179 } 00180 00181 PADAPTER_OBJECT 00182 NTAPI 00183 CDmaChannelInit::GetAdapterObject() 00184 { 00185 DPRINT("CDmaChannelInit_GetAdapterObject: this %p\n", this); 00186 return (PADAPTER_OBJECT)m_pAdapter; 00187 } 00188 00189 ULONG 00190 NTAPI 00191 CDmaChannelInit::MaximumBufferSize() 00192 { 00193 DPRINT("CDmaChannelInit_MaximumBufferSize: this %p\n", this); 00194 return m_MaximumBufferSize; 00195 } 00196 00197 #ifdef _MSC_VER 00198 00199 PHYSICAL_ADDRESS 00200 NTAPI 00201 CDmaChannelInit::PhysicalAddress() 00202 { 00203 DPRINT("CDmaChannelInit_PhysicalAdress: this %p Virtuell %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart); 00204 00205 return m_Address; 00206 } 00207 00208 #else 00209 00210 PHYSICAL_ADDRESS 00211 NTAPI 00212 CDmaChannelInit::PhysicalAddress( 00213 PPHYSICAL_ADDRESS Address) 00214 { 00215 DPRINT("CDmaChannelInit_PhysicalAdress: this %p Virtuell %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart); 00216 00217 PHYSICAL_ADDRESS Result; 00218 00219 Address->QuadPart = m_Address.QuadPart; 00220 Result.QuadPart = (ULONG_PTR)Address; 00221 return Result; 00222 } 00223 00224 00225 #endif 00226 00227 VOID 00228 NTAPI 00229 CDmaChannelInit::SetBufferSize( 00230 IN ULONG BufferSize) 00231 { 00232 DPRINT("CDmaChannelInit_SetBufferSize: this %p\n", this); 00233 m_BufferSize = BufferSize; 00234 00235 } 00236 00237 ULONG 00238 NTAPI 00239 CDmaChannelInit::BufferSize() 00240 { 00241 DPRINT("BufferSize %u\n", m_BufferSize); 00242 PC_ASSERT(m_BufferSize); 00243 return m_BufferSize; 00244 } 00245 00246 00247 PVOID 00248 NTAPI 00249 CDmaChannelInit::SystemAddress() 00250 { 00251 DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this); 00252 return m_Buffer; 00253 } 00254 00255 ULONG 00256 NTAPI 00257 CDmaChannelInit::TransferCount() 00258 { 00259 DPRINT("CDmaChannelInit_TransferCount: this %p\n", this); 00260 return m_LastTransferCount; 00261 } 00262 00263 ULONG 00264 NTAPI 00265 CDmaChannelInit::ReadCounter() 00266 { 00267 ULONG Counter; 00268 00269 PC_ASSERT_IRQL(DISPATCH_LEVEL); 00270 00271 Counter = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter); 00272 00273 if (!m_DmaStarted || Counter >= m_LastTransferCount) 00274 Counter = 0; 00275 00276 DPRINT("ReadCounter %u\n", Counter); 00277 00278 return Counter; 00279 } 00280 00281 IO_ALLOCATION_ACTION 00282 NTAPI 00283 AdapterControl( 00284 IN PDEVICE_OBJECT DeviceObject, 00285 IN PIRP Irp, 00286 IN PVOID MapRegisterBase, 00287 IN PVOID Context) 00288 { 00289 ULONG Length; 00290 CDmaChannelInit * This = (CDmaChannelInit*)Context; 00291 00292 Length = This->m_MapSize; 00293 This->m_MapRegisterBase = MapRegisterBase; 00294 00295 This->m_pAdapter->DmaOperations->MapTransfer(This->m_pAdapter, 00296 This->m_Mdl, 00297 MapRegisterBase, 00298 (PVOID)((ULONG_PTR)This->m_Mdl->StartVa + This->m_Mdl->ByteOffset), 00299 &Length, 00300 This->m_WriteToDevice); 00301 00302 if (Length == This->m_BufferSize) 00303 { 00304 This->m_DmaStarted = TRUE; 00305 } 00306 00307 return KeepObject; 00308 } 00309 00310 NTSTATUS 00311 NTAPI 00312 CDmaChannelInit::Start( 00313 ULONG MapSize, 00314 BOOLEAN WriteToDevice) 00315 { 00316 NTSTATUS Status; 00317 ULONG MapRegisters; 00318 KIRQL OldIrql; 00319 00320 DPRINT("CDmaChannelInit_Start: this %p\n", this); 00321 00322 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00323 00324 if (m_DmaStarted) 00325 return STATUS_UNSUCCESSFUL; 00326 00327 if (!m_Mdl) 00328 { 00329 m_Mdl = IoAllocateMdl(m_Buffer, m_MaximumBufferSize, FALSE, FALSE, NULL); 00330 if (!m_Mdl) 00331 { 00332 return STATUS_INSUFFICIENT_RESOURCES; 00333 } 00334 MmBuildMdlForNonPagedPool(m_Mdl); 00335 } 00336 00337 m_MapSize = MapSize; 00338 m_WriteToDevice = WriteToDevice; 00339 m_LastTransferCount = MapSize; 00340 00341 //FIXME 00342 // synchronize access 00343 // 00344 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00345 00346 MapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer, MapSize); 00347 Status = m_pAdapter->DmaOperations->AllocateAdapterChannel(m_pAdapter, m_pDeviceObject, MapRegisters, AdapterControl, (PVOID)this); 00348 KeLowerIrql(OldIrql); 00349 00350 if(!NT_SUCCESS(Status)) 00351 m_LastTransferCount = 0; 00352 00353 return Status; 00354 } 00355 00356 NTSTATUS 00357 NTAPI 00358 CDmaChannelInit::Stop() 00359 { 00360 KIRQL OldIrql; 00361 00362 DPRINT("CDmaChannelInit::Stop: this %p\n", this); 00363 PC_ASSERT_IRQL(DISPATCH_LEVEL); 00364 00365 if (!m_DmaStarted) 00366 return STATUS_SUCCESS; 00367 00368 m_pAdapter->DmaOperations->FlushAdapterBuffers(m_pAdapter, 00369 m_Mdl, 00370 m_MapRegisterBase, 00371 (PVOID)((ULONG_PTR)m_Mdl->StartVa + m_Mdl->ByteOffset), 00372 m_MapSize, 00373 m_WriteToDevice); 00374 00375 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00376 00377 m_pAdapter->DmaOperations->FreeAdapterChannel(m_pAdapter); 00378 00379 KeLowerIrql(OldIrql); 00380 00381 m_DmaStarted = FALSE; 00382 00383 IoFreeMdl(m_Mdl); 00384 m_Mdl = NULL; 00385 00386 return STATUS_SUCCESS; 00387 } 00388 00389 NTSTATUS 00390 NTAPI 00391 CDmaChannelInit::WaitForTC( 00392 ULONG Timeout) 00393 { 00394 ULONG RetryCount; 00395 ULONG BytesRemaining; 00396 ULONG PrevBytesRemaining; 00397 00398 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00399 00400 BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter); 00401 if (!BytesRemaining) 00402 { 00403 return STATUS_SUCCESS; 00404 } 00405 00406 RetryCount = Timeout / 10; 00407 PrevBytesRemaining = 0xFFFFFFFF; 00408 do 00409 { 00410 BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter); 00411 00412 if (!BytesRemaining) 00413 break; 00414 00415 if (PrevBytesRemaining == BytesRemaining) 00416 break; 00417 00418 KeStallExecutionProcessor(10); 00419 PrevBytesRemaining = BytesRemaining; 00420 00421 }while(RetryCount-- >= 1); 00422 00423 if (BytesRemaining) 00424 { 00425 return STATUS_UNSUCCESSFUL; 00426 } 00427 00428 return STATUS_SUCCESS; 00429 00430 } 00431 00432 NTSTATUS 00433 NTAPI 00434 CDmaChannelInit::Init( 00435 IN PDEVICE_DESCRIPTION DeviceDescription, 00436 IN PDEVICE_OBJECT DeviceObject) 00437 { 00438 INTERFACE_TYPE BusType; 00439 NTSTATUS Status; 00440 PDMA_ADAPTER Adapter; 00441 PPCLASS_DEVICE_EXTENSION DeviceExt; 00442 ULONG MapRegisters; 00443 ULONG ResultLength; 00444 00445 // Get bus type 00446 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyLegacyBusType, sizeof(BusType), (PVOID)&BusType, &ResultLength); 00447 if (NT_SUCCESS(Status)) 00448 { 00449 DeviceDescription->InterfaceType = BusType; 00450 } 00451 // Fetch device extension 00452 DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; 00453 // Acquire dma adapter 00454 Adapter = IoGetDmaAdapter(DeviceExt->PhysicalDeviceObject, DeviceDescription, &MapRegisters); 00455 if (!Adapter) 00456 { 00457 FreeItem(this, TAG_PORTCLASS); 00458 return STATUS_DEVICE_CONFIGURATION_ERROR; 00459 } 00460 00461 // initialize object 00462 m_pAdapter = Adapter; 00463 m_pDeviceObject = DeviceObject; 00464 m_MaximumBufferSize = DeviceDescription->MaximumLength; 00465 m_MaxMapRegisters = MapRegisters; 00466 00467 return STATUS_SUCCESS; 00468 } 00469 00470 NTSTATUS 00471 NTAPI 00472 PcNewDmaChannel( 00473 OUT PDMACHANNEL* OutDmaChannel, 00474 IN PUNKNOWN OuterUnknown OPTIONAL, 00475 IN POOL_TYPE PoolType, 00476 IN PDEVICE_DESCRIPTION DeviceDescription, 00477 IN PDEVICE_OBJECT DeviceObject) 00478 { 00479 NTSTATUS Status; 00480 CDmaChannelInit * This; 00481 00482 DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n", 00483 OutDmaChannel, OuterUnknown, PoolType, DeviceDescription, DeviceObject); 00484 00485 This = new(PoolType, TAG_PORTCLASS)CDmaChannelInit(OuterUnknown); 00486 if (!This) 00487 return STATUS_INSUFFICIENT_RESOURCES; 00488 00489 Status = This->QueryInterface(IID_IDmaChannel, (PVOID*)OutDmaChannel); 00490 00491 if (!NT_SUCCESS(Status)) 00492 { 00493 delete This; 00494 return Status; 00495 } 00496 00497 Status = This->Init(DeviceDescription, DeviceObject); 00498 00499 if (!NT_SUCCESS(Status)) 00500 { 00501 delete This; 00502 return Status; 00503 } 00504 00505 return Status; 00506 } Generated on Tue May 22 2012 04:32:30 for ReactOS by
1.7.6.1
|