Author: janderwald
Date: Sun Aug 2 13:40:38 2009
New Revision: 42334
URL:
http://svn.reactos.org/svn/reactos?rev=42334&view=rev
Log:
[KS]
- Implement KsQueryInformationFile
- Properly implement KsStreamIo
- Fix a desastreous bug in KsRemoveIrpFromCancelableQueue
- Implement KsMoveIrpsOnCancelableQueue
[PORTCLS]
- Switch portcls to use the provided ks irp queue function instead of the homegrown
IRP_MAPPING routines. Irp queueing is now faster and consumes less memory
- Return an allocated silence buffer when there are no mappings available
- HACK-Remove: Don't pre-complete any audio buffers now anymore. If you experience
audio stuttering, let me know
[SYSAUDIO, PORTCLS, KMIXER]
- FastRead / FastWrite routines must store their return values in the status block as
KsStreamIo now checks these
Modified:
trunk/reactos/drivers/ksfilter/ks/irp.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c
trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
trunk/reactos/drivers/wdm/audio/sysaudio/pin.c
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/irp.c?…
==============================================================================
--- trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] Sun Aug 2 13:40:38 2009
@@ -344,7 +344,7 @@
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
NTSTATUS
@@ -357,7 +357,13 @@
{
PDEVICE_OBJECT DeviceObject;
PFAST_IO_DISPATCH FastIoDispatch;
+ PIRP Irp;
+ PIO_STACK_LOCATION IoStack;
IO_STATUS_BLOCK IoStatus;
+ KEVENT Event;
+ LARGE_INTEGER Offset;
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
/* get related file object */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
@@ -386,10 +392,47 @@
}
}
}
-
- /* Implement Me */
-
- return STATUS_UNSUCCESSFUL;
+ /* clear event */
+ KeClearEvent(&FileObject->Event);
+
+ /* initialize event */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+ /* set offset to zero */
+ Offset.QuadPart = 0L;
+
+ /* build the request */
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION,
IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event,
&StatusBlock);
+
+ if (!Irp)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* get next stack location */
+ IoStack = IoGetNextIrpStackLocation(Irp);
+
+ /* setup parameters */
+ IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass;
+ IoStack->Parameters.QueryFile.Length = Length;
+ Irp->AssociatedIrp.SystemBuffer = FileInformation;
+
+
+ /* call the driver */
+ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
+
+ if (Status == STATUS_PENDING)
+ {
+ /* wait for the operation to complete */
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+
+ /* is object sync */
+ if (FileObject->Flags & FO_SYNCHRONOUS_IO)
+ Status = FileObject->FinalStatus;
+ else
+ Status = StatusBlock.Status;
+ }
+
+ /* done */
+ return Status;
}
/*
@@ -506,77 +549,104 @@
PIRP Irp;
PIO_STACK_LOCATION IoStack;
PDEVICE_OBJECT DeviceObject;
- ULONG Code;
NTSTATUS Status;
LARGE_INTEGER Offset;
PKSIOBJECT_HEADER ObjectHeader;
-
-
- if (Flags == KSSTREAM_READ)
- Code = IRP_MJ_READ;
- else if (Flags == KSSTREAM_WRITE)
- Code = IRP_MJ_WRITE;
- else
- return STATUS_INVALID_PARAMETER;
-
+ BOOLEAN Ret;
+
+ /* get related device object */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
- if (!DeviceObject)
- return STATUS_INVALID_PARAMETER;
-
+ /* sanity check */
+ ASSERT(DeviceObject != NULL);
+
+ /* is there a event provided */
if (Event)
{
- KeResetEvent(Event);
- }
-
- //ASSERT(DeviceObject->DeviceType == FILE_DEVICE_KS);
- ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
- ASSERT(ObjectHeader);
- if (Code == IRP_MJ_READ)
- {
- if (ObjectHeader->DispatchTable.FastRead)
- {
- if (ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE,
0, StreamHeaders, IoStatusBlock, DeviceObject))
+ /* reset event */
+ KeClearEvent(Event);
+ }
+
+ if (RequestorMode || ExGetPreviousMode() == KernelMode)
+ {
+ /* requestor is from kernel land */
+ ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
+
+ if (ObjectHeader)
+ {
+ /* there is a object header */
+ if (Flags == KSSTREAM_READ)
{
- return STATUS_SUCCESS;
+ /* is fast read supported */
+ if (ObjectHeader->DispatchTable.FastRead)
+ {
+ /* call fast read dispatch routine */
+ Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL,
Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
+
+ if (Ret)
+ {
+ /* the request was handeled */
+ return IoStatusBlock->Status;
+ }
+ }
}
- }
- }
- else
- {
- if (ObjectHeader->DispatchTable.FastWrite)
- {
- if (ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE,
0, StreamHeaders, IoStatusBlock, DeviceObject))
+ else if (Flags == KSSTREAM_WRITE)
{
- return STATUS_SUCCESS;
+ /* is fast write supported */
+ if (ObjectHeader->DispatchTable.FastWrite)
+ {
+ /* call fast write dispatch routine */
+ Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL,
Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
+
+ if (Ret)
+ {
+ /* the request was handeled */
+ return IoStatusBlock->Status;
+ }
+ }
}
}
}
+ /* clear file object event */
+ KeClearEvent(&FileObject->Event);
+
+ /* set the offset to zero */
Offset.QuadPart = 0LL;
- Irp = IoBuildSynchronousFsdRequest(Code, DeviceObject, (PVOID)StreamHeaders, Length,
&Offset, Event, IoStatusBlock);
+
+ /* now build the irp */
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
+ DeviceObject, (PVOID)StreamHeaders, Length,
&Offset, Event, IoStatusBlock);
if (!Irp)
{
- return STATUS_UNSUCCESSFUL;
- }
-
+ /* not enough memory */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* setup irp parameters */
+ Irp->RequestorMode = RequestorMode;
+ Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->UserBuffer = StreamHeaders;
+
+ /* get next irp stack location */
+ IoStack = IoGetNextIrpStackLocation(Irp);
+ /* setup stack parameters */
+ IoStack->FileObject = FileObject;
+ IoStack->Parameters.DeviceIoControl.InputBufferLength = Length;
+ IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders;
+ IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ?
IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
if (CompletionRoutine)
{
- IoSetCompletionRoutine(Irp,
- CompletionRoutine,
- CompletionContext,
- (CompletionInvocationFlags & KsInvokeOnSuccess),
- (CompletionInvocationFlags & KsInvokeOnError),
- (CompletionInvocationFlags & KsInvokeOnCancel));
- }
-
- IoStack = IoGetNextIrpStackLocation(Irp);
- IoStack->FileObject = FileObject;
-
+ /* setup completion routine for async processing */
+ IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext,
(CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags &
KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
+ }
+
+ /* now call the driver */
Status = IoCallDriver(DeviceObject, Irp);
+ /* done */
return Status;
}
-
/*
@unimplemented
@@ -933,7 +1003,7 @@
}
/* get irp offset */
- Irp = (PIRP)CONTAINING_RECORD(Irp, IRP, Tail.Overlay.ListEntry);
+ Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
if (Irp->Cancel)
{
@@ -988,7 +1058,7 @@
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
NTSTATUS
@@ -1002,8 +1072,114 @@
IN PFNKSIRPLISTCALLBACK ListCallback,
IN PVOID Context)
{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
+ KIRQL OldLevel;
+ PLIST_ENTRY SrcEntry;
+ PIRP Irp;
+ NTSTATUS Status;
+
+ if (!DestinationLock)
+ {
+ /* no destination lock just acquire the source lock */
+ KeAcquireSpinLock(SourceLock, &OldLevel);
+ }
+ else
+ {
+ /* acquire cancel spinlock */
+ IoAcquireCancelSpinLock(&OldLevel);
+
+ /* now acquire source lock */
+ KeAcquireSpinLockAtDpcLevel(SourceLock);
+
+ /* now acquire destination lock */
+ KeAcquireSpinLockAtDpcLevel(DestinationLock);
+ }
+
+ /* point to list head */
+ SrcEntry = SourceList;
+
+ /* now move all irps */
+ while(TRUE)
+ {
+ if (ListLocation == KsListEntryTail)
+ {
+ /* move queue downwards */
+ SrcEntry = SrcEntry->Flink;
+ }
+ else
+ {
+ /* move queue upwards */
+ SrcEntry = SrcEntry->Blink;
+ }
+
+ if (SrcEntry == DestinationList)
+ {
+ /* eof list reached */
+ break;
+ }
+
+ /* get irp offset */
+ Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry);
+
+ /* now check if irp can be moved */
+ Status = ListCallback(Irp, Context);
+
+ /* check if irp can be moved */
+ if (Status == STATUS_SUCCESS)
+ {
+ /* remove irp from src list */
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+ if (ListLocation == KsListEntryTail)
+ {
+ /* insert irp end of list */
+ InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry);
+ }
+ else
+ {
+ /* insert irp head of list */
+ InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry);
+ }
+
+ /* do we need to update the irp lock */
+ if (DestinationLock)
+ {
+ /* update irp lock */
+ KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock;
+ }
+ }
+ else
+ {
+ if (Status != STATUS_NO_MATCH)
+ {
+ /* callback decided to stop enumeration */
+ break;
+ }
+
+ /* reset return value */
+ Status = STATUS_SUCCESS;
+ }
+ }
+
+ if (!DestinationLock)
+ {
+ /* release source lock */
+ KeReleaseSpinLock(SourceLock, OldLevel);
+ }
+ else
+ {
+ /* now release destination lock */
+ KeReleaseSpinLockFromDpcLevel(DestinationLock);
+
+ /* now release source lock */
+ KeReleaseSpinLockFromDpcLevel(SourceLock);
+
+
+ /* now release cancel spinlock */
+ IoReleaseCancelSpinLock(OldLevel);
+ }
+
+ /* done */
+ return Status;
}
/*
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -197,7 +197,8 @@
IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FrameSize,
- IN ULONG Alignment);
+ IN ULONG Alignment,
+ IN PVOID SilenceBuffer);
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
IN PUCHAR Buffer,
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -8,17 +8,6 @@
#include "private.h"
-typedef struct _IRP_MAPPING_
-{
- LIST_ENTRY Entry;
- PVOID Buffer;
- ULONG BufferSize;
- ULONG OriginalBufferSize;
- PVOID OriginalBuffer;
- PIRP Irp;
-
- PVOID Tag;
-}IRP_MAPPING, *PIRP_MAPPING;
typedef struct
{
@@ -33,9 +22,11 @@
KSPIN_CONNECT *ConnectDetails;
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
- KSPIN_LOCK Lock;
- LIST_ENTRY ListHead;
- LIST_ENTRY FreeHead;
+ KSPIN_LOCK IrpListLock;
+ LIST_ENTRY IrpList;
+ LIST_ENTRY FreeIrpList;
+ PIRP Irp;
+ PVOID SilenceBuffer;
ULONG OutOfMapping;
ULONG MaxFrameSize;
@@ -44,28 +35,6 @@
}IIrpQueueImpl;
-VOID
-NTAPI
-FreeMappingRoutine(
- PIRP_MAPPING CurMapping)
-{
- ASSERT(CurMapping);
-
- if (CurMapping->Irp)
- {
- CurMapping->Irp->IoStatus.Information = CurMapping->OriginalBufferSize;
- CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
- }
-
- if (CurMapping->OriginalBuffer)
- {
- ExFreePool(CurMapping->OriginalBuffer);
- }
-
- ExFreePool(CurMapping);
-}
-
NTSTATUS
NTAPI
IIrpQueue_fnQueryInterface(
@@ -121,19 +90,21 @@
IN PKSDATAFORMAT DataFormat,
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FrameSize,
- IN ULONG Alignment)
+ IN ULONG Alignment,
+ IN PVOID SilenceBuffer)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
This->ConnectDetails = ConnectDetails;
This->DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
This->MaxFrameSize = FrameSize;
+ This->SilenceBuffer = SilenceBuffer;
This->Alignment = Alignment;
This->MinimumDataThreshold =
((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nAvgBytesPerSec / 3;
- InitializeListHead(&This->ListHead);
- InitializeListHead(&This->FreeHead);
- KeInitializeSpinLock(&This->Lock);
+ InitializeListHead(&This->IrpList);
+ InitializeListHead(&This->FreeIrpList);
+ KeInitializeSpinLock(&This->IrpListLock);
return STATUS_SUCCESS;
}
@@ -146,84 +117,35 @@
IN ULONG BufferSize,
IN PIRP Irp)
{
- PIRP_MAPPING Mapping = NULL;
- KSSTREAM_HEADER * Header = (KSSTREAM_HEADER*)Buffer;
- ULONG Index, NumMappings, Offset;
- IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
-
-
- if (This->MaxFrameSize)
- {
- if (This->MaxFrameSize > Header->DataUsed)
- {
- /* small mapping */
- NumMappings = 1;
- }
- else
- {
- ULONG Rest = Header->DataUsed % This->MaxFrameSize;
-
- NumMappings = Header->DataUsed / This->MaxFrameSize;
- if (Rest)
- {
- NumMappings++;
- }
- }
- }
- else
- {
- /* no framesize restriction */
- NumMappings = 1;
- }
-
- for(Index = 0; Index < NumMappings; Index++)
- {
- Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
- if (!Mapping)
- {
- DPRINT("OutOfMemory\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- if (Index)
- Offset = Index * This->MaxFrameSize;
- else
- Offset = 0;
-
- Mapping->Buffer = (PVOID)UlongToPtr((PtrToUlong(Header->Data) + Offset + 3)
& ~(0x3));
-
- if (This->MaxFrameSize)
- Mapping->BufferSize = min(Header->DataUsed - Offset,
This->MaxFrameSize);
- else
- Mapping->BufferSize = Header->DataUsed;
-
- Mapping->OriginalBufferSize = Header->FrameExtent;
- Mapping->OriginalBuffer = NULL;
- Mapping->Irp = NULL;
- Mapping->Tag = NULL;
-
- This->NumDataAvailable += Mapping->BufferSize;
-
- if (Index == NumMappings - 1)
- {
- /* last mapping should free the irp if provided */
- Mapping->OriginalBuffer = Header->Data;
- Mapping->Irp = Irp;
- }
-
- ExInterlockedInsertTailList(&This->ListHead, &Mapping->Entry,
&This->Lock);
- (void)InterlockedIncrement((volatile long*)&This->NumMappings);
-
- DPRINT("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu
NumDataAvailable %lu Mapping %p FrameSize %u\n", This->NumMappings,
Mapping->BufferSize, This->NumDataAvailable, Mapping, This->MaxFrameSize);
- }
-
- if (Irp)
- {
- Irp->IoStatus.Status = STATUS_PENDING;
- Irp->IoStatus.Information = 0;
- IoMarkIrpPending(Irp);
- }
-
+ PKSSTREAM_HEADER Header;
+ IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+
+ /* FIXME
+ * irp should contain the stream header...
+ */
+
+ /* get stream header */
+ Header = (KSSTREAM_HEADER*)Buffer;
+
+ /* dont exceed max frame size */
+ ASSERT(This->MaxFrameSize >= Header->DataUsed);
+
+ /* hack untill stream probing is ready */
+ Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
+
+ /* increment num mappings */
+ InterlockedIncrement(&This->NumMappings);
+
+ /* increment num data available */
+ This->NumDataAvailable += Header->DataUsed;
+
+ /* mark irp as pending */
+ IoMarkIrpPending(Irp);
+
+ /* add irp to cancelable queue */
+ KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp,
KsListEntryTail, NULL);
+
+ /* done */
return STATUS_SUCCESS;
}
@@ -234,55 +156,102 @@
OUT PUCHAR * Buffer,
OUT PULONG BufferSize)
{
-
- PIRP_MAPPING CurMapping;
- IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
- PLIST_ENTRY CurEntry;
-
- CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
- if (!CurEntry)
- {
+ PIRP Irp;
+ ULONG Offset;
+ PKSSTREAM_HEADER StreamHeader;
+ IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+
+ /* check if there is an irp in the partially processed */
+ if (This->Irp)
+ {
+ /* use last irp */
+ Irp = This->Irp;
+ Offset = This->CurrentOffset;
+ /* TODO cancel irp when required */
+ ASSERT(Irp->Cancel == FALSE);
+ }
+ else
+ {
+ /* get a fresh new irp from the queue */
+ This->Irp = Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList,
&This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+ This->CurrentOffset = Offset = 0;
+ }
+
+ if (!Irp)
+ {
+ /* no irp available, use silence buffer */
+ *Buffer = This->SilenceBuffer;
+ *BufferSize = This->MaxFrameSize;
+ /* flag for port wave pci driver */
+ This->OutOfMapping = TRUE;
+ /* indicate flag to restart fast buffering */
This->StartStream = FALSE;
- This->OutOfMapping = TRUE;
- return STATUS_UNSUCCESSFUL;
- }
-
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
- *Buffer = (PUCHAR)CurMapping->Buffer + This->CurrentOffset;
- *BufferSize = CurMapping->BufferSize - This->CurrentOffset;
- ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry,
&This->Lock);
+ return STATUS_SUCCESS;
+ }
+
+ /* HACK get stream header */
+ StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
+
+ /* sanity check */
+ ASSERT(StreamHeader);
+
+ /* store buffersize */
+ *BufferSize = StreamHeader->DataUsed - Offset;
+
+ /* store buffer */
+ *Buffer = &((PUCHAR)StreamHeader->Data)[Offset];
+
+ /* unset flag that no irps are available */
This->OutOfMapping = FALSE;
return STATUS_SUCCESS;
}
-
-
VOID
NTAPI
IIrpQueue_fnUpdateMapping(
IN IIrpQueue *iface,
IN ULONG BytesWritten)
{
- PLIST_ENTRY CurEntry;
- PIRP_MAPPING CurMapping;
- IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
-
- CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
-
+ PKSSTREAM_HEADER StreamHeader;
+ IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+
+ if (!This->Irp)
+ {
+ /* silence buffer was used */
+ return;
+ }
+
+ /* HACK get stream header */
+ StreamHeader = (PKSSTREAM_HEADER)This->Irp->Tail.Overlay.DriverContext[2];
+
+ /* add to current offset */
This->CurrentOffset += BytesWritten;
+
+ /* decrement available data counter */
This->NumDataAvailable -= BytesWritten;
- if (CurMapping->BufferSize <= This->CurrentOffset)
- {
+ if (This->CurrentOffset >= StreamHeader->DataUsed)
+ {
+ /* irp has been processed completly */
+ This->Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ /* frame extend contains the original request size, DataUsed contains the real
buffer size
+ * is different when kmixer performs channel conversion, upsampling etc
+ */
+ This->Irp->IoStatus.Information = StreamHeader->FrameExtent;
+
+ /* free stream data, no tag as wdmaud.drv does it atm */
+ ExFreePool(StreamHeader->Data);
+
+ /* free stream header, no tag as wdmaud.drv allocates it atm */
+ ExFreePool(StreamHeader);
+
+ /* complete the request */
+ IoCompleteRequest(This->Irp, IO_SOUND_INCREMENT);
+ /* remove irp as it is complete */
+ This->Irp = NULL;
This->CurrentOffset = 0;
- InterlockedDecrement(&This->NumMappings);
- FreeMappingRoutine(CurMapping);
- }
- else
- {
- ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry,
&This->Lock);
}
}
@@ -293,6 +262,7 @@
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+ /* returns the amount of mappings available */
return This->NumMappings;
}
@@ -302,6 +272,7 @@
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+ /* returns the amount of audio stream data available */
return This->NumDataAvailable;
}
@@ -363,50 +334,45 @@
OUT PULONG ByteCount,
OUT PULONG Flags)
{
- PIRP_MAPPING CurMapping;
- PLIST_ENTRY CurEntry;
+ PKSSTREAM_HEADER StreamHeader;
+ PIRP Irp;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
*Flags = 0;
ASSERT(Tag != NULL);
-
- CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
- if (!CurEntry)
- {
+ /* get an irp from the queue */
+ Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList,
&This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+
+ /* check if there is an irp */
+ if (!Irp)
+ {
+ /* no irp available */
This->OutOfMapping = TRUE;
This->StartStream = FALSE;
return STATUS_UNSUCCESSFUL;
}
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
-
- *PhysicalAddress = MmGetPhysicalAddress(CurMapping->Buffer);
- *VirtualAddress = CurMapping->Buffer;
- *ByteCount = CurMapping->BufferSize;
-
+ /* HACK get stream header */
+ StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
+
+ /* store mapping in the free list */
+ ExInterlockedInsertTailList(&This->FreeIrpList,
&Irp->Tail.Overlay.ListEntry, &This->IrpListLock);
+
+ /* return mapping */
+ *PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data);
+ *VirtualAddress = StreamHeader->Data;
+ *ByteCount = StreamHeader->DataUsed;
+
+ /* decrement mapping count */
InterlockedDecrement(&This->NumMappings);
- This->NumDataAvailable -= CurMapping->BufferSize;
-
- if (CurMapping->OriginalBuffer)
- {
- /* last partial buffer */
- *Flags = 1;
-
- /* store tag */
- CurMapping->Tag = Tag;
-
- /* insert into list to free later */
- ExInterlockedInsertTailList(&This->FreeHead, &CurMapping->Entry,
&This->Lock);
- DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p Mapping %p\n", Tag,
CurMapping);
- }
- else
- {
- /* we can free this entry now */
- FreeItem(CurMapping, TAG_PORTCLASS);
- DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p Mapping %p FREED\n", Tag,
CurMapping);
- }
-
+ /* decrement num data available */
+ This->NumDataAvailable -= StreamHeader->DataUsed;
+
+ /* store tag in irp */
+ Irp->Tail.Overlay.DriverContext[3] = Tag;
+
+ /* done */
return STATUS_SUCCESS;
}
@@ -416,30 +382,44 @@
IN IIrpQueue *iface,
IN PVOID Tag)
{
- PIRP_MAPPING CurMapping = NULL;
+ PIRP Irp;
PLIST_ENTRY CurEntry;
+ PKSSTREAM_HEADER StreamHeader;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
- CurEntry = ExInterlockedRemoveHeadList(&This->FreeHead, &This->Lock);
- if (!CurMapping)
- {
- return STATUS_SUCCESS;
- }
-
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
- if (CurMapping->Tag != Tag)
- {
- /* the released mapping is not the last one */
- ExInterlockedInsertHeadList(&This->FreeHead, &CurMapping->Entry,
&This->Lock);
- return STATUS_SUCCESS;
- }
-
- /* last mapping of the irp, free irp */
- DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p Mapping %p FREED\n", Tag,
CurMapping);
-
- FreeMappingRoutine(CurMapping);
+ /* remove irp from used list */
+ CurEntry = ExInterlockedRemoveHeadList(&This->FreeIrpList,
&This->IrpListLock);
+ /* sanity check */
+ ASSERT(CurEntry);
+
+ /* get irp from list entry */
+ Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
+
+ /* HACK get stream header */
+ StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
+
+ /* driver must release items in the same order */
+ ASSERT(Irp->Tail.Overlay.DriverContext[3] == Tag);
+
+ /* irp has been processed completly */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ /* frame extend contains the original request size, DataUsed contains the real buffer
size
+ * is different when kmixer performs channel conversion, upsampling etc
+ */
+ Irp->IoStatus.Information = StreamHeader->FrameExtent;
+
+ /* free stream data, no tag as wdmaud.drv does it atm */
+ ExFreePool(StreamHeader->Data);
+
+ /* free stream header, no tag as wdmaud.drv allocates it atm */
+ ExFreePool(StreamHeader);
+
+ /* complete the request */
+ IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
+
return STATUS_SUCCESS;
}
@@ -457,24 +437,7 @@
IIrpQueue_fnPrintQueueStatus(
IN IIrpQueue *iface)
{
- PIRP_MAPPING CurMapping = NULL;
- PLIST_ENTRY CurEntry;
-
- IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
- KeAcquireSpinLockAtDpcLevel(&This->Lock);
-
- CurEntry = This->ListHead.Flink;
- DPRINT("IIrpQueue_fnPrintQueueStatus % u ===============\n",
This->NumMappings);
-
- while (CurEntry != &This->ListHead)
- {
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
- DPRINT("Mapping %p Size %u Original %p\n", CurMapping,
CurMapping->BufferSize, CurMapping->OriginalBuffer);
- CurEntry = CurEntry->Flink;
- }
-
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
- DPRINT("IIrpQueue_fnPrintQueueStatus ===============\n");
+
}
VOID
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -1135,7 +1135,7 @@
This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
}
- Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
This->Format, DeviceObject, 0, 0);
+ Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
This->Format, DeviceObject, 0, 0, NULL /*FIXME*/);
if (!NT_SUCCESS(Status))
{
DPRINT1("IrpQueue_Init failed with %x\n", Status);
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1]
(original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] Sun Aug
2 13:40:38 2009
@@ -970,37 +970,24 @@
PrePostRatio = (This->PreCompleted * 100) / This->TotalPackets;
MinData = This->IrpQueue->lpVtbl->NumData(This->IrpQueue);
- DPRINT("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u State %x
MinData %u Ratio %u\n", This->TotalPackets, This->PreCompleted,
This->PostCompleted, This->State,
This->IrpQueue->lpVtbl->NumData(This->IrpQueue), PrePostRatio);
+ DPRINT1("IPortPinWaveCyclic_fnFastWrite entered Total %u Pre %u Post %u State %x
MinData %u Ratio %u\n", This->TotalPackets, This->PreCompleted,
This->PostCompleted, This->State,
This->IrpQueue->lpVtbl->NumData(This->IrpQueue), PrePostRatio);
Packet = (PCONTEXT_WRITE)Buffer;
-
- if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
- {
- Irp = Packet->Irp;
- StatusBlock->Status = STATUS_PENDING;
- InterlockedIncrement((PLONG)&This->PostCompleted);
- }
- else
- {
- Irp = NULL;
- Packet->Irp->IoStatus.Status = STATUS_SUCCESS;
- Packet->Irp->IoStatus.Information = Packet->Header.FrameExtent;
- IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
- StatusBlock->Status = STATUS_SUCCESS;
- InterlockedIncrement((PLONG)&This->PreCompleted);
- }
+ Irp = Packet->Irp;
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer,
Length, Irp);
if (!NT_SUCCESS(Status))
return FALSE;
- if (This->State != KSSTATE_RUN &&
This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE)
+ if (This->State != KSSTATE_RUN)
{
SetStreamState(This, KSSTATE_RUN);
/* some should initiate a state request but didnt do it */
DPRINT1("Starting stream with %lu mappings Status %x\n",
This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), Status);
}
+
+ StatusBlock->Status = STATUS_PENDING;
return TRUE;
}
@@ -1021,6 +1008,7 @@
PKSDATAFORMAT DataFormat;
PDEVICE_OBJECT DeviceObject;
BOOL Capture;
+ PVOID SilenceBuffer;
//IDrmAudioStream * DrmAudio = NULL;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
@@ -1114,13 +1102,18 @@
Status = This->Stream->lpVtbl->SetNotificationFreq(This->Stream, 10,
&This->FrameSize);
- Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
DataFormat, DeviceObject, This->FrameSize, 0);
+ SilenceBuffer = AllocateItem(NonPagedPool, This->FrameSize, TAG_PORTCLASS);
+ if (!SilenceBuffer)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ This->Stream->lpVtbl->Silence(This->Stream, SilenceBuffer,
This->FrameSize);
+
+ Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
DataFormat, DeviceObject, This->FrameSize, 0, SilenceBuffer);
if (!NT_SUCCESS(Status))
{
This->IrpQueue->lpVtbl->Release(This->IrpQueue);
return Status;
}
-
//This->Stream->lpVtbl->SetFormat(This->Stream,
(PKSDATAFORMAT)This->Format);
DPRINT1("Setting state to acquire %x\n",
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE));
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.c [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -1069,7 +1069,7 @@
if (!NT_SUCCESS(Status))
return Status;
- Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
This->Format, DeviceObject, This->AllocatorFraming.FrameSize,
This->AllocatorFraming.FileAlignment);
+ Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
This->Format, DeviceObject, This->AllocatorFraming.FrameSize,
This->AllocatorFraming.FileAlignment, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("IrpQueue_Init failed with %x\n", Status);
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -992,7 +992,7 @@
goto cleanup;
}
- Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
DataFormat, DeviceObject, 0, 0);
+ Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails,
DataFormat, DeviceObject, 0, 0, NULL);
if (!NT_SUCCESS(Status))
{
goto cleanup;
Modified: trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/filters/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c [iso-8859-1] Sun Aug 2 13:40:38
2009
@@ -668,6 +668,8 @@
}
}
+ IoStatus->Status = Status;
+
if (NT_SUCCESS(Status))
return TRUE;
else
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -706,6 +706,28 @@
NTSTATUS
NTAPI
+WdmAudWriteCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP LowerIrp,
+ IN PVOID Context)
+{
+ PIRP Irp;
+ ASSERT(LowerIrp->PendingReturned == FALSE);
+ /* get original irp */
+ Irp = (PIRP)Context;
+
+ /* save status */
+ Irp->IoStatus.Status = LowerIrp->IoStatus.Status;
+ Irp->IoStatus.Information = LowerIrp->IoStatus.Information;
+ /* complete request */
+ IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
+ /* return success to free irp */
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+NTAPI
WdmAudWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
@@ -715,11 +737,13 @@
PWDMAUD_CLIENT ClientInfo;
NTSTATUS Status = STATUS_SUCCESS;
PUCHAR Buffer;
+ PFILE_OBJECT FileObject;
+ PMDL Mdl;
+ //PIRP LowerIrp;
PCONTEXT_WRITE Packet;
- PFILE_OBJECT FileObject;
+ PVOID SystemBuffer;
+ //LARGE_INTEGER Offset;
IO_STATUS_BLOCK IoStatusBlock;
- PMDL Mdl;
- PVOID SystemBuffer;
IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -826,14 +850,51 @@
ExFreePool(Packet);
IoFreeMdl(Mdl);
ObDereferenceObject(FileObject);
- return SetIrpIoStatus(Irp, Status, 0);
+ return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
}
RtlMoveMemory(Buffer, SystemBuffer, DeviceInfo->BufferSize);
MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
- KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet,
sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, KernelMode);
+#if 1
+ KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet,
sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, UserMode);
+ /* dereference file object */
ObDereferenceObject(FileObject);
return IoStatusBlock.Status;
-}
+#else
+ Offset.QuadPart = 0L;
+
+ /* now build the irp */
+ LowerIrp = IoBuildAsynchronousFsdRequest (IRP_MJ_WRITE,
+ IoGetRelatedDeviceObject(FileObject),
+ Packet,
+ sizeof(KSSTREAM_HEADER),
+ &Offset,
+ NULL);
+
+ if (!LowerIrp)
+ {
+ /* failed to create an associated irp */
+ ExFreePool(Buffer);
+ ExFreePool(Packet);
+ ObDereferenceObject(FileObject);
+
+ return SetIrpIoStatus(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
+ }
+
+ /* set a completion routine */
+ IoSetCompletionRoutine(LowerIrp, WdmAudWriteCompletion, (PVOID)Irp, TRUE, TRUE,
TRUE);
+
+ /* mark irp as pending */
+ IoMarkIrpPending(Irp);
+
+ /* call the driver */
+ Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), LowerIrp);
+
+ /* dereference file object */
+ ObDereferenceObject(FileObject);
+
+ return STATUS_PENDING;
+#endif
+}
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] Sun Aug 2
13:40:38 2009
@@ -56,15 +56,6 @@
PIRP Irp;
}CONTEXT_WRITE, *PCONTEXT_WRITE;
-
-typedef struct
-{
- PIRP Irp;
- IO_STATUS_BLOCK StatusBlock;
- ULONG Length;
-}WRITE_CONTEXT, *PWRITE_CONTEXT;
-
-
NTSTATUS
WdmAudRegisterDeviceInterface(
IN PDEVICE_OBJECT PhysicalDeviceObject,
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/pin.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/pin.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/pin.c [iso-8859-1] Sun Aug 2 13:40:38 2009
@@ -161,7 +161,7 @@
/* call the portcls audio pin */
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
- MmGetMdlVirtualAddress(Irp->MdlAddress),
+ Irp->UserBuffer,
IoStack->Parameters.Write.Length,
NULL,
0,
@@ -379,13 +379,14 @@
Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
if (NT_SUCCESS(Status))
{
- Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus,
Buffer, Length, KSSTREAM_WRITE, KernelMode);
+ Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus,
Buffer, Length, KSSTREAM_WRITE, UserMode);
ObDereferenceObject(RealFileObject);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("Mixing stream failed with %lx\n", Status);
+ DbgBreakPoint();
return FALSE;
}
}
@@ -394,11 +395,11 @@
if (!NT_SUCCESS(Status))
return FALSE;
- Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer,
Length, KSSTREAM_WRITE, KernelMode);
+ Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer,
Length, KSSTREAM_WRITE, UserMode);
ObDereferenceObject(RealFileObject);
- if (Status == STATUS_SUCCESS)
+ if (NT_SUCCESS(Status))
return TRUE;
else
return FALSE;