ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dma_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.