- Define private interface IPortWaveRTStreamInit in order to deal with PHYSICAL_ADDRESS as return value

- Implement reading/writing into cyclic buffer for IPortPinWaveRT 
- Allocate an audio buffer when the pin is initialized. This needs to be changed once KSPROPERTY_RTAUDIO_BUFFER is implemented
- Fix a bug in PcNewPort
- Remove obsolete code from IPortWavePci
- Return the allocated MDL from IPortWaveRTStream::AllocateContiguousPagesForMdl
- Create a system thread when using IServiceGroup::RequestDelayedService
- ReactOS now partly supports Vista audio driver model

svn path=/trunk/; revision=41497
This commit is contained in:
Johannes Anderwald 2009-06-20 23:37:55 +00:00
parent 9c621c0524
commit eef3e1deca
7 changed files with 316 additions and 130 deletions

View file

@ -710,4 +710,62 @@ typedef IPortFilterTopology *PPORTFILTERTOPOLOGY;
#undef INTERFACE
/*****************************************************************************
* IPortWaveRTStreamInit
*****************************************************************************
*/
#undef INTERFACE
#define INTERFACE IPortWaveRTStreamInit
DECLARE_INTERFACE_(IPortWaveRTStreamInit, IUnknown)
{
DEFINE_ABSTRACT_UNKNOWN()
STDMETHOD_(PMDL, AllocatePagesForMdl)
( THIS_
IN PHYSICAL_ADDRESS HighAddress,
IN SIZE_T TotalBytes
) PURE;
STDMETHOD_(PMDL, AllocateContiguousPagesForMdl)
( THIS_
IN PHYSICAL_ADDRESS LowAddress,
IN PHYSICAL_ADDRESS HighAddress,
IN SIZE_T TotalBytes
) PURE;
STDMETHOD_(PVOID, MapAllocatedPages)
( THIS_
IN PMDL MemoryDescriptorList,
IN MEMORY_CACHING_TYPE CacheType
) PURE;
STDMETHOD_(VOID, UnmapAllocatedPages)
( THIS_
IN PVOID BaseAddress,
IN PMDL MemoryDescriptorList
) PURE;
STDMETHOD_(VOID, FreePagesFromMdl)
( THIS_
IN PMDL MemoryDescriptorList
) PURE;
STDMETHOD_(ULONG, GetPhysicalPagesCount)
( THIS_
IN PMDL MemoryDescriptorList
) PURE;
STDMETHOD_(PHYSICAL_ADDRESS, GetPhysicalPageAddress)
( THIS_
IN PPHYSICAL_ADDRESS Address,
IN PMDL MemoryDescriptorList,
IN ULONG Index
) PURE;
};
#undef INTERFACE
#endif

View file

@ -59,6 +59,85 @@ SetStreamState(
IN IPortPinWaveRTImpl * This,
IN KSSTATE State);
static
VOID
UpdateCommonBuffer(
IPortPinWaveRTImpl * This,
ULONG Position)
{
ULONG BufferLength;
ULONG BytesToCopy;
ULONG BufferSize;
PUCHAR Buffer;
NTSTATUS Status;
BufferLength = Position - This->CommonBufferOffset;
while(BufferLength)
{
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
return;
BytesToCopy = min(BufferLength, BufferSize);
if (This->Capture)
{
RtlMoveMemory(Buffer, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, BytesToCopy);
}
else
{
RtlMoveMemory((PUCHAR)This->CommonBuffer + This->CommonBufferOffset, Buffer, BytesToCopy);
}
This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy);
This->CommonBufferOffset += BytesToCopy;
BufferLength = Position - This->CommonBufferOffset;
}
}
static
VOID
UpdateCommonBufferOverlap(
IPortPinWaveRTImpl * This,
ULONG Position)
{
ULONG BufferLength;
ULONG BytesToCopy;
ULONG BufferSize;
PUCHAR Buffer;
NTSTATUS Status;
BufferLength = This->CommonBufferSize - This->CommonBufferOffset;
while(BufferLength)
{
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
return;
BytesToCopy = min(BufferLength, BufferSize);
if (This->Capture)
{
RtlMoveMemory(Buffer, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, BytesToCopy);
}
else
{
RtlMoveMemory((PUCHAR)This->CommonBuffer + This->CommonBufferOffset, Buffer, BytesToCopy);
}
This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy);
This->CommonBufferOffset += BytesToCopy;
BufferLength = This->CommonBufferSize - This->CommonBufferOffset;
}
This->CommonBufferOffset = 0;
UpdateCommonBuffer(This, Position);
}
//==================================================================================================================================
static
NTSTATUS
@ -137,14 +216,16 @@ IServiceSink_fnRequestService(
}
Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
DPRINT("PlayOffset %llu WriteOffset %llu %u Buffer %p BufferSize %u\n", Position.PlayOffset, Position.WriteOffset, Buffer, This->CommonBufferSize, BufferSize);
DPRINT("PlayOffset %lu WriteOffset %lu Buffer %p BufferSize %u CommonBufferSize %u\n", Position.PlayOffset, Position.WriteOffset, Buffer, BufferSize, This->CommonBufferSize);
//FIXME
// implement writing into cyclic buffer
//
/* reschedule the timer */
This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
if (Position.PlayOffset < This->CommonBufferOffset)
{
UpdateCommonBufferOverlap(This, Position.PlayOffset);
}
else if (Position.PlayOffset >= This->CommonBufferOffset)
{
UpdateCommonBuffer(This, Position.PlayOffset);
}
}
static IServiceSinkVtbl vt_IServiceSink =
@ -962,18 +1043,25 @@ IPortPinWaveRT_fnInit(
/* minimum delay of 10 milisec */
This->Delay = Int32x32To64(min(max(Latency.ChipsetDelay + Latency.CodecDelay + Latency.FifoSize, 10), 10), -10000);
Status = This->Stream->lpVtbl->AllocateAudioBuffer(This->Stream, 16384, &This->Mdl, &This->CommonBufferSize, &This->CommonBufferOffset, &This->CacheType);
Status = This->Stream->lpVtbl->AllocateAudioBuffer(This->Stream, 16384 * 11, &This->Mdl, &This->CommonBufferSize, &This->CommonBufferOffset, &This->CacheType);
if (!NT_SUCCESS(Status))
{
DPRINT1("AllocateAudioBuffer failed with %x\n", Status);
goto cleanup;
}
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
This->State = KSSTATE_STOP;
This->Capture = Capture;
This->CommonBuffer = MmGetSystemAddressForMdlSafe(This->Mdl, NormalPagePriority);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get system address %x\n", Status);
IoFreeMdl(This->Mdl);
This->Mdl = NULL;
goto cleanup;
}
This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
DPRINT1("Setting state to acquire %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE));
DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));
This->State = KSSTATE_PAUSE;
return STATUS_SUCCESS;
cleanup:
@ -995,12 +1083,20 @@ cleanup:
This->ServiceGroup = NULL;
}
if (This->PortStream)
if (This->Stream)
{
This->PortStream->lpVtbl->Release(This->PortStream);
This->PortStream = NULL;
This->Stream->lpVtbl->Release(This->Stream);
This->Stream = NULL;
}
else
{
if (This->PortStream)
{
This->PortStream->lpVtbl->Release(This->PortStream);
This->PortStream = NULL;
}
}
return Status;
}

View file

@ -40,10 +40,8 @@ PcNewPort(
Status = NewPortWaveCyclic(OutPort);
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortWavePci))
Status = NewPortWavePci(OutPort);
#if (NTDDI_VERSION >= NTDDI_VISTA)
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortWavePci))
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortWaveRT))
Status = NewPortWaveRT(OutPort);
#endif
else
{

View file

@ -22,7 +22,6 @@ typedef struct
PMINIPORTWAVEPCI Miniport;
PDEVICE_OBJECT pDeviceObject;
KDPC Dpc;
BOOL bInitialized;
PRESOURCELIST pResourceList;
PSERVICEGROUP ServiceGroup;
@ -331,26 +330,6 @@ IPortWavePci_fnRelease(
return This->ref;
}
VOID
NTAPI
ServiceNotifyRoutine(
IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
DPRINT("ServiceNotifyRoutine entered %p %p %p\n", DeferredContext, SystemArgument1, SystemArgument2);
IPortWavePciImpl * This = (IPortWavePciImpl*)DeferredContext;
if (This->ServiceGroup && This->bInitialized)
{
DPRINT("ServiceGroup %p\n", This->ServiceGroup);
This->ServiceGroup->lpVtbl->RequestService(This->ServiceGroup);
}
}
NTSTATUS
NTAPI
IPortWavePci_fnInit(
@ -385,16 +364,12 @@ IPortWavePci_fnInit(
return STATUS_INVALID_PARAMETER;
}
/* initialize the dpc */
KeInitializeDpc(&This->Dpc, ServiceNotifyRoutine, (PVOID)This);
/* Initialize port object */
This->Miniport = Miniport;
This->pDeviceObject = DeviceObject;
This->bInitialized = TRUE;
This->pResourceList = ResourceList;
/* increment reference on miniport adapter */
Miniport->lpVtbl->AddRef(Miniport);
/* increment reference on resource list */

View file

@ -10,7 +10,7 @@
typedef struct
{
IPortWaveRTStreamVtbl *lpVtbl;
IPortWaveRTStreamInitVtbl *lpVtbl;
LONG ref;
}IPortWaveRTStreamImpl;
@ -21,8 +21,8 @@ typedef struct
static
NTSTATUS
NTAPI
IPortWaveRTStream_fnQueryInterface(
IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnQueryInterface(
IPortWaveRTStreamInit * iface,
IN REFIID refiid,
OUT PVOID* Output)
{
@ -46,8 +46,8 @@ IPortWaveRTStream_fnQueryInterface(
static
ULONG
NTAPI
IPortWaveRTStream_fnAddRef(
IPortWaveRTStream* iface)
IPortWaveRTStreamInit_fnAddRef(
IPortWaveRTStreamInit * iface)
{
IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
DPRINT("IPortWaveRTStream_fnAddRef entered\n");
@ -61,8 +61,8 @@ IPortWaveRTStream_fnAddRef(
static
ULONG
NTAPI
IPortWaveRTStream_fnRelease(
IPortWaveRTStream* iface)
IPortWaveRTStreamInit_fnRelease(
IPortWaveRTStreamInit * iface)
{
IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
@ -85,8 +85,8 @@ IPortWaveRTStream_fnRelease(
static
PMDL
NTAPI
IPortWaveRTStream_fnAllocatePagesForMdl(
IN IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnAllocatePagesForMdl(
IN IPortWaveRTStreamInit * iface,
IN PHYSICAL_ADDRESS HighAddress,
IN SIZE_T TotalBytes)
{
@ -99,8 +99,8 @@ IPortWaveRTStream_fnAllocatePagesForMdl(
static
PMDL
NTAPI
IPortWaveRTStream_fnAllocateContiguousPagesForMdl(
IN IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnAllocateContiguousPagesForMdl(
IN IPortWaveRTStreamInit * iface,
IN PHYSICAL_ADDRESS LowAddress,
IN PHYSICAL_ADDRESS HighAddress,
IN SIZE_T TotalBytes)
@ -129,12 +129,14 @@ IPortWaveRTStream_fnAllocateContiguousPagesForMdl(
if (MmGetMdlByteCount(Mdl) < TotalBytes)
{
DPRINT1("ByteCount %u Required %u\n", MmGetMdlByteCount(Mdl), TotalBytes);
MmFreePagesFromMdl(Mdl);
ExFreePool(Mdl);
return NULL;
}
return NULL;
DPRINT("Result %p\n", Mdl);
return Mdl;
}
/*
@ -143,8 +145,8 @@ IPortWaveRTStream_fnAllocateContiguousPagesForMdl(
static
PVOID
NTAPI
IPortWaveRTStream_fnMapAllocatedPages(
IN IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnMapAllocatedPages(
IN IPortWaveRTStreamInit * iface,
IN PMDL MemoryDescriptorList,
IN MEMORY_CACHING_TYPE CacheType)
{
@ -157,8 +159,8 @@ IPortWaveRTStream_fnMapAllocatedPages(
static
VOID
NTAPI
IPortWaveRTStream_fnUnmapAllocatedPages(
IN IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnUnmapAllocatedPages(
IN IPortWaveRTStreamInit * iface,
IN PVOID BaseAddress,
IN PMDL MemoryDescriptorList)
{
@ -171,8 +173,8 @@ IPortWaveRTStream_fnUnmapAllocatedPages(
static
VOID
NTAPI
IPortWaveRTStream_fnFreePagesFromMdl(
IN IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnFreePagesFromMdl(
IN IPortWaveRTStreamInit * iface,
IN PMDL MemoryDescriptorList)
{
MmFreePagesFromMdl(MemoryDescriptorList);
@ -185,8 +187,8 @@ IPortWaveRTStream_fnFreePagesFromMdl(
static
ULONG
NTAPI
IPortWaveRTStream_fnGetPhysicalPagesCount(
IN IPortWaveRTStream* iface,
IPortWaveRTStreamInit_fnGetPhysicalPagesCount(
IN IPortWaveRTStreamInit * iface,
IN PMDL MemoryDescriptorList)
{
return ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
@ -198,13 +200,15 @@ IPortWaveRTStream_fnGetPhysicalPagesCount(
static
PHYSICAL_ADDRESS
NTAPI
IPortWaveRTStream_fnGetPhysicalPageAddress(
IN IPortWaveRTStream* iface,
IN PMDL MemoryDescriptorList,
IPortWaveRTStreamInit_fnGetPhysicalPageAddress(
IN IPortWaveRTStreamInit * iface,
IN PPHYSICAL_ADDRESS Address,
IN PMDL MemoryDescriptorList,
IN ULONG Index)
{
PVOID Buffer;
ULONG Pages;
PHYSICAL_ADDRESS Result, Addr;
Pages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
if (Pages <= Index)
@ -214,21 +218,26 @@ IPortWaveRTStream_fnGetPhysicalPageAddress(
}
Buffer = UlongToPtr(PtrToUlong(MmGetSystemAddressForMdl(MemoryDescriptorList)) + Index * PAGE_SIZE);
return MmGetPhysicalAddress(Buffer);
Addr = MmGetPhysicalAddress(Buffer);
Address->QuadPart = Addr.QuadPart;
Result.QuadPart = (PtrToUlong(Address));
return Result;
}
static IPortWaveRTStreamVtbl vt_PortWaveRTStream =
static IPortWaveRTStreamInitVtbl vt_PortWaveRTStream =
{
IPortWaveRTStream_fnQueryInterface,
IPortWaveRTStream_fnAddRef,
IPortWaveRTStream_fnRelease,
IPortWaveRTStream_fnAllocatePagesForMdl,
IPortWaveRTStream_fnAllocateContiguousPagesForMdl,
IPortWaveRTStream_fnMapAllocatedPages,
IPortWaveRTStream_fnUnmapAllocatedPages,
IPortWaveRTStream_fnFreePagesFromMdl,
IPortWaveRTStream_fnGetPhysicalPagesCount,
IPortWaveRTStream_fnGetPhysicalPageAddress
IPortWaveRTStreamInit_fnQueryInterface,
IPortWaveRTStreamInit_fnAddRef,
IPortWaveRTStreamInit_fnRelease,
IPortWaveRTStreamInit_fnAllocatePagesForMdl,
IPortWaveRTStreamInit_fnAllocateContiguousPagesForMdl,
IPortWaveRTStreamInit_fnMapAllocatedPages,
IPortWaveRTStreamInit_fnUnmapAllocatedPages,
IPortWaveRTStreamInit_fnFreePagesFromMdl,
IPortWaveRTStreamInit_fnGetPhysicalPagesCount,
IPortWaveRTStreamInit_fnGetPhysicalPageAddress
};
NTSTATUS

View file

@ -7,9 +7,11 @@
#ifndef PORTCLS_PRIVATE_H
#define PORTCLS_PRIVATE_H
//#define _KS_NO_ANONYMOUS_STRUCTURES_
#include <ntddk.h>
#include <portcls.h>
#define NDEBUG
#define YDEBUG
#include <debug.h>
#include <dmusicks.h>
@ -182,24 +184,6 @@ NTAPI
NewIrpQueue(
IN IIrpQueue **Queue);
typedef struct
{
LIST_ENTRY Entry;
KSOBJECT_HEADER ObjectHeader;
}SUBDEVICE_ENTRY;
typedef struct
{
LIST_ENTRY Entry;
ISubdevice * FromSubDevice;
LPWSTR FromUnicodeString;
ULONG FromPin;
ISubdevice * ToSubDevice;
LPWSTR ToUnicodeString;
ULONG ToPin;
}PHYSICAL_CONNECTION;
NTSTATUS
NTAPI
TopologyPropertyHandler(
@ -214,37 +198,6 @@ PinPropertyHandler(
IN PKSIDENTIFIER Request,
IN OUT PVOID Data);
typedef struct
{
KSDEVICE_HEADER KsDeviceHeader;
PDEVICE_OBJECT PhysicalDeviceObject;
PDEVICE_OBJECT PrevDeviceObject;
PCPFNSTARTDEVICE StartDevice;
ULONG_PTR Unused[4];
IAdapterPowerManagement * AdapterPowerManagement;
ULONG MaxSubDevices;
KSOBJECT_CREATE_ITEM * CreateItems;
IResourceList* resources;
LIST_ENTRY SubDeviceList;
LIST_ENTRY PhysicalConnectionList;
} PCLASS_DEVICE_EXTENSION, *PPCLASS_DEVICE_EXTENSION;
typedef struct
{
KSSTREAM_HEADER Header;
PIRP Irp;
}CONTEXT_WRITE, *PCONTEXT_WRITE;
typedef struct
{
PVOID Pin;
PIO_WORKITEM WorkItem;
PIRP Irp;
}CLOSESTREAM_CONTEXT, *PCLOSESTREAM_CONTEXT;
NTSTATUS
NTAPI
PcDmaMasterDescription(
@ -353,4 +306,52 @@ DEFINE_KSPROPERTY_TABLE(PinSet) {\
DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(PropGeneral)\
}
typedef struct
{
LIST_ENTRY Entry;
KSOBJECT_HEADER ObjectHeader;
}SUBDEVICE_ENTRY;
typedef struct
{
LIST_ENTRY Entry;
ISubdevice * FromSubDevice;
LPWSTR FromUnicodeString;
ULONG FromPin;
ISubdevice * ToSubDevice;
LPWSTR ToUnicodeString;
ULONG ToPin;
}PHYSICAL_CONNECTION;
typedef struct
{
KSDEVICE_HEADER KsDeviceHeader;
PDEVICE_OBJECT PhysicalDeviceObject;
PDEVICE_OBJECT PrevDeviceObject;
PCPFNSTARTDEVICE StartDevice;
ULONG_PTR Unused[4];
IAdapterPowerManagement * AdapterPowerManagement;
ULONG MaxSubDevices;
KSOBJECT_CREATE_ITEM * CreateItems;
IResourceList* resources;
LIST_ENTRY SubDeviceList;
LIST_ENTRY PhysicalConnectionList;
} PCLASS_DEVICE_EXTENSION, *PPCLASS_DEVICE_EXTENSION;
typedef struct
{
KSSTREAM_HEADER Header;
PIRP Irp;
}CONTEXT_WRITE, *PCONTEXT_WRITE;
typedef struct
{
PVOID Pin;
PIO_WORKITEM WorkItem;
PIRP Irp;
}CLOSESTREAM_CONTEXT, *PCLOSESTREAM_CONTEXT;
#endif

View file

@ -26,6 +26,8 @@ typedef struct
BOOL TimerActive;
KTIMER Timer;
KDPC Dpc;
KEVENT Event;
LONG ThreadActive;
}IServiceGroupImpl;
@ -94,6 +96,10 @@ IServiceGroup_fnRelease(
FreeItem(Entry, TAG_PORTCLASS);
}
KeCancelTimer(&This->Timer);
if (This->ThreadActive)
{
KeSetEvent(&This->Event, 0, TRUE);
}
FreeItem(This, TAG_PORTCLASS);
return 0;
}
@ -203,18 +209,60 @@ IServiceGroupDpc(
}
}
VOID
NTAPI
ServiceGroupThread(IN PVOID StartContext)
{
NTSTATUS Status;
KWAIT_BLOCK WaitBlockArray[2];
PVOID WaitObjects[2];
IServiceGroupImpl * This = (IServiceGroupImpl*)StartContext;
/* Set thread state */
InterlockedIncrement(&This->ThreadActive);
/* Setup the wait objects */
WaitObjects[0] = &This->Timer;
WaitObjects[1] = &This->Event;
do
{
/* Wait on our objects */
Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, WaitBlockArray);
switch(Status)
{
case STATUS_WAIT_0:
IServiceGroupDpc(&This->Dpc, (PVOID)This, NULL, NULL);
break;
case STATUS_WAIT_1:
PsTerminateSystemThread(STATUS_SUCCESS);
break;
}
}while(TRUE);
}
VOID
NTAPI
IServiceGroup_fnSupportDelayedService(
IN IServiceGroup * iface)
{
NTSTATUS Status;
HANDLE ThreadHandle;
IServiceGroupImpl * This = (IServiceGroupImpl*)iface;
ASSERT_IRQL(DISPATCH_LEVEL);
if (!This->Initialized)
if (This->Initialized)
return;
KeInitializeTimerEx(&This->Timer, NotificationTimer);
Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, 0, NULL, ServiceGroupThread, (PVOID)This);
if (NT_SUCCESS(Status))
{
KeInitializeTimerEx(&This->Timer, NotificationTimer);
ZwClose(ThreadHandle);
This->Initialized = TRUE;
}
}
@ -290,6 +338,7 @@ PcNewServiceGroup(
This->ref = 1;
KeInitializeDpc(&This->Dpc, IServiceGroupDpc, (PVOID)This);
KeSetImportanceDpc(&This->Dpc, HighImportance);
KeInitializeEvent(&This->Event, NotificationEvent, FALSE);
InitializeListHead(&This->ServiceSinkHead);
*OutServiceGroup = (PSERVICEGROUP)&This->lpVtbl;