- 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

svn path=/trunk/; revision=42334
This commit is contained in:
Johannes Anderwald 2009-08-02 11:40:38 +00:00
parent 47f744578f
commit 9061b8ee40
11 changed files with 468 additions and 280 deletions

View file

@ -344,7 +344,7 @@ KsWriteFile(
}
/*
@unimplemented
@implemented
*/
KSDDKAPI
NTSTATUS
@ -357,7 +357,13 @@ KsQueryInformationFile(
{
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 @@ KsQueryInformationFile(
}
}
}
/* clear event */
KeClearEvent(&FileObject->Event);
/* Implement Me */
/* initialize event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
return STATUS_UNSUCCESSFUL;
/* 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,78 +549,105 @@ KsStreamIo(
PIRP Irp;
PIO_STACK_LOCATION IoStack;
PDEVICE_OBJECT DeviceObject;
ULONG Code;
NTSTATUS Status;
LARGE_INTEGER Offset;
PKSIOBJECT_HEADER ObjectHeader;
BOOLEAN Ret;
if (Flags == KSSTREAM_READ)
Code = IRP_MJ_READ;
else if (Flags == KSSTREAM_WRITE)
Code = IRP_MJ_WRITE;
else
return STATUS_INVALID_PARAMETER;
/* 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);
/* reset event */
KeClearEvent(Event);
}
//ASSERT(DeviceObject->DeviceType == FILE_DEVICE_KS);
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
ASSERT(ObjectHeader);
if (Code == IRP_MJ_READ)
if (RequestorMode || ExGetPreviousMode() == KernelMode)
{
if (ObjectHeader->DispatchTable.FastRead)
/* requestor is from kernel land */
ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
if (ObjectHeader)
{
if (ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
/* 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));
/* setup completion routine for async processing */
IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
}
IoStack = IoGetNextIrpStackLocation(Irp);
IoStack->FileObject = FileObject;
/* now call the driver */
Status = IoCallDriver(DeviceObject, Irp);
/* done */
return Status;
}
/*
@unimplemented
*/
@ -933,7 +1003,7 @@ KsRemoveIrpFromCancelableQueue(
}
/* 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 @@ KsRemoveIrpFromCancelableQueue(
}
/*
@unimplemented
@implemented
*/
KSDDKAPI
NTSTATUS
@ -1002,8 +1072,114 @@ KsMoveIrpsOnCancelableQueue(
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;
}
/*

View file

@ -197,7 +197,8 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
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,

View file

@ -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 @@ typedef struct
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 @@ typedef struct
}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 @@ IIrpQueue_fnInit(
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 @@ IIrpQueue_fnAddMapping(
IN ULONG BufferSize,
IN PIRP Irp)
{
PIRP_MAPPING Mapping = NULL;
KSSTREAM_HEADER * Header = (KSSTREAM_HEADER*)Buffer;
ULONG Index, NumMappings, Offset;
PKSSTREAM_HEADER Header;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* FIXME
* irp should contain the stream header...
*/
if (This->MaxFrameSize)
{
if (This->MaxFrameSize > Header->DataUsed)
{
/* small mapping */
NumMappings = 1;
}
else
{
ULONG Rest = Header->DataUsed % This->MaxFrameSize;
/* get stream header */
Header = (KSSTREAM_HEADER*)Buffer;
NumMappings = Header->DataUsed / This->MaxFrameSize;
if (Rest)
{
NumMappings++;
}
}
}
else
{
/* no framesize restriction */
NumMappings = 1;
}
/* dont exceed max frame size */
ASSERT(This->MaxFrameSize >= Header->DataUsed);
for(Index = 0; Index < NumMappings; Index++)
{
Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
if (!Mapping)
{
DPRINT("OutOfMemory\n");
return STATUS_UNSUCCESSFUL;
}
/* hack untill stream probing is ready */
Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
if (Index)
Offset = Index * This->MaxFrameSize;
else
Offset = 0;
/* increment num mappings */
InterlockedIncrement(&This->NumMappings);
Mapping->Buffer = (PVOID)UlongToPtr((PtrToUlong(Header->Data) + Offset + 3) & ~(0x3));
/* increment num data available */
This->NumDataAvailable += Header->DataUsed;
if (This->MaxFrameSize)
Mapping->BufferSize = min(Header->DataUsed - Offset, This->MaxFrameSize);
else
Mapping->BufferSize = Header->DataUsed;
/* mark irp as pending */
IoMarkIrpPending(Irp);
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);
}
/* add irp to cancelable queue */
KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL);
/* done */
return STATUS_SUCCESS;
}
@ -234,55 +156,102 @@ IIrpQueue_fnGetMapping(
OUT PUCHAR * Buffer,
OUT PULONG BufferSize)
{
PIRP_MAPPING CurMapping;
PIRP Irp;
ULONG Offset;
PKSSTREAM_HEADER StreamHeader;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
PLIST_ENTRY CurEntry;
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
if (!CurEntry)
/* check if there is an irp in the partially processed */
if (This->Irp)
{
This->StartStream = FALSE;
This->OutOfMapping = TRUE;
return STATUS_UNSUCCESSFUL;
/* 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;
}
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);
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;
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;
PKSSTREAM_HEADER StreamHeader;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
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 @@ IIrpQueue_fnNumMappings(
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* returns the amount of mappings available */
return This->NumMappings;
}
@ -302,6 +272,7 @@ IIrpQueue_fnNumData(
IN IIrpQueue *iface)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
/* returns the amount of audio stream data available */
return This->NumDataAvailable;
}
@ -363,50 +334,45 @@ IIrpQueue_fnGetMappingWithTag(
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);
/* get an irp from the queue */
Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
if (!CurEntry)
/* 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);
/* HACK get stream header */
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
*PhysicalAddress = MmGetPhysicalAddress(CurMapping->Buffer);
*VirtualAddress = CurMapping->Buffer;
*ByteCount = CurMapping->BufferSize;
/* 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;
/* decrement num data available */
This->NumDataAvailable -= StreamHeader->DataUsed;
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);
}
/* store tag in irp */
Irp->Tail.Overlay.DriverContext[3] = Tag;
/* done */
return STATUS_SUCCESS;
}
@ -416,30 +382,44 @@ IIrpQueue_fnReleaseMappingWithTag(
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;
}
/* remove irp from used list */
CurEntry = ExInterlockedRemoveHeadList(&This->FreeIrpList, &This->IrpListLock);
/* sanity check */
ASSERT(CurEntry);
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;
}
/* get irp from list entry */
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
/* last mapping of the irp, free irp */
DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p Mapping %p FREED\n", Tag, CurMapping);
/* 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);
FreeMappingRoutine(CurMapping);
return STATUS_SUCCESS;
}
@ -457,24 +437,7 @@ NTAPI
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

View file

@ -1135,7 +1135,7 @@ IPortPinDMus_fnInit(
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);

View file

@ -970,38 +970,25 @@ IPortPinWaveCyclic_fnFastWrite(
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 @@ IPortPinWaveCyclic_fnInit(
PKSDATAFORMAT DataFormat;
PDEVICE_OBJECT DeviceObject;
BOOL Capture;
PVOID SilenceBuffer;
//IDrmAudioStream * DrmAudio = NULL;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
@ -1114,14 +1102,19 @@ IPortPinWaveCyclic_fnInit(
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));
DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE));

View file

@ -1069,7 +1069,7 @@ IPortPinWavePci_fnInit(
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);

View file

@ -992,7 +992,7 @@ IPortPinWaveRT_fnInit(
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;

View file

@ -668,6 +668,8 @@ Pin_fnFastWrite(
}
}
IoStatus->Status = Status;
if (NT_SUCCESS(Status))
return TRUE;
else

View file

@ -704,6 +704,28 @@ WdmAudDeviceControl(
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
}
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(
@ -715,11 +737,13 @@ WdmAudWrite(
PWDMAUD_CLIENT ClientInfo;
NTSTATUS Status = STATUS_SUCCESS;
PUCHAR Buffer;
PCONTEXT_WRITE Packet;
PFILE_OBJECT FileObject;
IO_STATUS_BLOCK IoStatusBlock;
PMDL Mdl;
//PIRP LowerIrp;
PCONTEXT_WRITE Packet;
PVOID SystemBuffer;
//LARGE_INTEGER Offset;
IO_STATUS_BLOCK IoStatusBlock;
IoStack = IoGetCurrentIrpStackLocation(Irp);
@ -826,14 +850,51 @@ WdmAudWrite(
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
}

View file

@ -56,15 +56,6 @@ typedef struct
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,

View file

@ -161,7 +161,7 @@ Pin_fnWrite(
/* 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 @@ Pin_fnFastWrite(
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 @@ Pin_fnFastWrite(
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;