Author: janderwald Date: Fri Mar 6 22:06:21 2009 New Revision: 39893
URL: http://svn.reactos.org/svn/reactos?rev=39893&view=rev Log: - Implement a fast read / fast write path with KsStreamIo - Fix 2 bugs in KsRegister*Worker code - Implement fast write support for the general purpose dispatcher in portcls - Implement a IIrpQueue object will queue pending irp requests - Refactor IPinWaveCyclic interrupt handling code to work with IIrpQueue - Handle wave out request in IRP_MJ_WRITE and submit them using KsStreamIo -
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c trunk/reactos/drivers/ksfilter/ks/worker.c trunk/reactos/drivers/wdm/audio/backpln/portcls/adapter.c trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.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_wavecyclic.c trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c trunk/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h trunk/reactos/drivers/wdm/audio/drivers/directory.rbuild trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.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?r... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -1077,6 +1077,8 @@ ULONG Code; NTSTATUS Status; LARGE_INTEGER Offset; + PKSIOBJECT_HEADER ObjectHeader; +
if (Flags == KSSTREAM_READ) Code = IRP_MJ_READ; @@ -1092,6 +1094,30 @@ 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)) + { + return STATUS_SUCCESS; + } + } + } + else + { + if (ObjectHeader->DispatchTable.FastWrite) + { + if (ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject)) + { + return STATUS_SUCCESS; + } + } }
Offset.QuadPart = 0LL;
Modified: trunk/reactos/drivers/ksfilter/ks/worker.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/worker.... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/worker.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/worker.c [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -43,7 +43,7 @@ KsWorker->Counter = 0; KsWorker->WorkItemActive = 0; KsWorker->WorkItem = NULL; - KsWorker->DeleteInProgress = TRUE; + KsWorker->DeleteInProgress = FALSE; KeInitializeSpinLock(&KsWorker->Lock); KeInitializeEvent(&KsWorker->Event, NotificationEvent, FALSE);
@@ -181,6 +181,9 @@ if (!KsWorker->DeleteInProgress) { ExQueueWorkItem(WorkItem, KsWorker->Type); + } + else + { Status = STATUS_UNSUCCESSFUL; }
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/adapter.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/adapter.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/adapter.c [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -200,7 +200,8 @@ return status; }
-NTSTATUS NTAPI +NTSTATUS +NTAPI PcRegisterSubdevice( IN PDEVICE_OBJECT DeviceObject, IN PWCHAR Name, @@ -215,16 +216,24 @@
DPRINT1("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject, Name, Unknown);
+ /* check if all parameters are valid */ if (!DeviceObject || !Name || !Unknown) { DPRINT("PcRegisterSubdevice invalid parameter\n"); return STATUS_INVALID_PARAMETER; }
+ /* get device extension */ DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + if (!DeviceExt) + { + /* should not happen */ + KeBugCheck(0); return STATUS_UNSUCCESSFUL; - + } + + /* look up our undocumented interface */ Status = Unknown->lpVtbl->QueryInterface(Unknown, &IID_ISubdevice, (LPVOID)&SubDevice); if (!NT_SUCCESS(Status)) {
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -215,9 +215,12 @@ PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { + IIrpTarget * IrpTarget; DPRINT1("Dispatch_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
- return FALSE; + IrpTarget = (IIrpTarget *)FileObject->FsContext2; + + return IrpTarget->lpVtbl->FastWrite(IrpTarget, FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); }
static KSDISPATCH_TABLE DispatchTable = @@ -244,6 +247,7 @@ NTSTATUS Status; KSOBJECT_HEADER ObjectHeader; PKSOBJECT_CREATE_ITEM CreateItem; + PIO_STACK_LOCATION IoStack;
CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM), TAG_PORTCLASS); if (!CreateItem) @@ -251,6 +255,11 @@
CreateItem->Context = (PVOID)Target;
+ IoStack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(IoStack->FileObject); + + IoStack->FileObject->FsContext2 = (PVOID)Target; + Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable); DPRINT1("KsAllocateObjectHeader result %x\n", Status); 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/p... ============================================================================== --- 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] Fri Mar 6 22:06:21 2009 @@ -180,6 +180,44 @@ };
/***************************************************************************** + * IIrpQueue + ***************************************************************************** + */ + +#undef INTERFACE +#define INTERFACE IIrpQueue + +DECLARE_INTERFACE_(IIrpQueue, IUnknown) +{ + DEFINE_ABSTRACT_UNKNOWN() + + STDMETHOD_(NTSTATUS, Init)(THIS_ + IN KSPIN_CONNECT *ConnectDetails, + IN PDEVICE_OBJECT DeviceObject); + + STDMETHOD_(NTSTATUS, AddMapping)(THIS_ + IN PUCHAR Buffer, + IN ULONG BufferSize, + IN PIRP Irp); + + STDMETHOD_(NTSTATUS, GetMapping)(THIS_ + OUT PUCHAR * Buffer, + OUT PULONG BufferSize); + + STDMETHOD_(VOID, UpdateMapping)(THIS_ + IN ULONG BytesWritten); + + STDMETHOD_(ULONG, NumMappings)(THIS); + + STDMETHOD_(ULONG, MinMappings)(THIS); + + STDMETHOD_(ULONG, MaxMappings)(THIS); + +}; + + + +/***************************************************************************** * IKsWorkSink ***************************************************************************** */
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- 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] Fri Mar 6 22:06:21 2009 @@ -1,4 +1,244 @@ - +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: drivers/multimedia/portcls/irpstream.c + * PURPOSE: IRP Stream handling + * PROGRAMMER: Johannes Anderwald + * + * HISTORY: + * 27 Jan 07 Created + */ + +#include "private.h" + +typedef struct _IRP_MAPPING_ +{ + KSSTREAM_HEADER *Header; + PIRP Irp; + LIST_ENTRY Entry; + struct _IRP_MAPPING_ * Next; +}IRP_MAPPING, *PIRP_MAPPING; + +#define MAX_MAPPING (100) + +typedef struct +{ + IIrpQueueVtbl *lpVtbl; + + LONG ref; + + ULONG CurrentOffset; + ULONG NextMapping; + LONG NumMappings; + IN KSPIN_CONNECT *ConnectDetails; + + PIRP_MAPPING FirstMap; + PIRP_MAPPING LastMap; +}IIrpQueueImpl; + +VOID +NTAPI +DpcRoutine( + IN struct _KDPC *Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2); + + +NTSTATUS +NTAPI +IIrpQueue_fnQueryInterface( + IIrpQueue* iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + if (IsEqualGUIDAligned(refiid, &IID_IUnknown)) + { + *Output = &This->lpVtbl; + _InterlockedIncrement(&This->ref); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + +ULONG +NTAPI +IIrpQueue_fnAddRef( + IIrpQueue* iface) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + return _InterlockedIncrement(&This->ref); +} + +ULONG +NTAPI +IIrpQueue_fnRelease( + IIrpQueue* iface) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + _InterlockedDecrement(&This->ref); + + if (This->ref == 0) + { + FreeItem(This, TAG_PORTCLASS); + return 0; + } + /* Return new reference count */ + return This->ref; +} + + +NTSTATUS +NTAPI +IIrpQueue_fnInit( + IN IIrpQueue *iface, + IN KSPIN_CONNECT *ConnectDetails, + IN PDEVICE_OBJECT DeviceObject) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + This->ConnectDetails = ConnectDetails; + + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +IIrpQueue_fnAddMapping( + IN IIrpQueue *iface, + IN PUCHAR Buffer, + IN ULONG BufferSize, + IN PIRP Irp) +{ + PIRP_MAPPING Mapping; + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + Mapping = ExAllocatePool(NonPagedPool, sizeof(IRP_MAPPING)); + if (!Mapping) + return STATUS_UNSUCCESSFUL; + + Mapping->Header = (KSSTREAM_HEADER*)Buffer; + Mapping->Irp = Irp; + + if (!This->FirstMap) + This->FirstMap = Mapping; + else + This->LastMap->Next = Mapping; + + This->LastMap = Mapping; + + InterlockedIncrement(&This->NumMappings); + + DPRINT1("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu\n", This->NumMappings, Mapping->Header->DataUsed); + + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +IIrpQueue_fnGetMapping( + IN IIrpQueue *iface, + OUT PUCHAR * Buffer, + OUT PULONG BufferSize) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + if (!This->FirstMap) + return STATUS_UNSUCCESSFUL; + + *Buffer = (PUCHAR)This->FirstMap->Header->Data + This->CurrentOffset; + *BufferSize = This->FirstMap->Header->DataUsed - This->CurrentOffset; + + return STATUS_SUCCESS; +} + + + +VOID +NTAPI +IIrpQueue_fnUpdateMapping( + IN IIrpQueue *iface, + IN ULONG BytesWritten) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + PIRP_MAPPING Mapping; + + This->CurrentOffset += BytesWritten; + + if (This->FirstMap->Header->DataUsed <=This->CurrentOffset) + { + This->CurrentOffset = 0; + Mapping = This->FirstMap; + This->FirstMap = This->FirstMap->Next; + + //ExFreePool(Mapping->Header->Data); + //ExFreePool(Mapping->Header); + //IoCompleteRequest(Mapping->Irp, IO_NO_INCREMENT); + //ExFreePool(Mapping); + } +} + +ULONG +NTAPI +IIrpQueue_fnNumMappings( + IN IIrpQueue *iface) +{ + IIrpQueueImpl * This = (IIrpQueueImpl*)iface; + + return This->NumMappings; +} + +ULONG +NTAPI +IIrpQueue_fnMaxMappings( + IN IIrpQueue *iface) +{ + return MAX_MAPPING; +} + +ULONG +NTAPI +IIrpQueue_fnMinMappings( + IN IIrpQueue *iface) +{ + return MAX_MAPPING / 4; +} + +static IIrpQueueVtbl vt_IIrpQueue = +{ + IIrpQueue_fnQueryInterface, + IIrpQueue_fnAddRef, + IIrpQueue_fnRelease, + IIrpQueue_fnInit, + IIrpQueue_fnAddMapping, + IIrpQueue_fnGetMapping, + IIrpQueue_fnUpdateMapping, + IIrpQueue_fnNumMappings, + IIrpQueue_fnMinMappings, + IIrpQueue_fnMaxMappings +}; + + +NTSTATUS +NTAPI +NewIrpQueue( + IN IIrpQueue **Queue) +{ + IIrpQueueImpl *This = AllocateItem(NonPagedPool, sizeof(IIrpQueueImpl), TAG_PORTCLASS); + if (!This) + return STATUS_INSUFFICIENT_RESOURCES; + + This->ref = 1; + This->lpVtbl = &vt_IIrpQueue; + + *Queue = (IIrpQueue*)This; + return STATUS_SUCCESS; + +}
NTSTATUS NewIrpStreamPhysical(
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- 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] Fri Mar 6 22:06:21 2009 @@ -16,19 +16,17 @@ KSSTATE State; PKSDATAFORMAT Format;
- LIST_ENTRY QueueHead; - KSPIN_LOCK QueueLock; - PVOID CommonBuffer; ULONG CommonBufferSize; ULONG CommonBufferOffset;
- PIRP ActiveIrp; + IIrpQueue * IrpQueue; + PUCHAR ActiveIrpBuffer; ULONG ActiveIrpBufferSize; ULONG ActiveIrpOffset; ULONG DelayedRequestInProgress; - + ULONG RetryCount;
}IPortPinWaveCyclicImpl;
@@ -101,88 +99,72 @@ IServiceSink* iface) { ULONG Position; - ULONG BufferLength, IrpLength, BytesToCopy; + ULONG BufferLength, BytesToCopy; NTSTATUS Status; + PUCHAR Buffer; + ULONG BufferSize;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
- if (This->ActiveIrp && This->ActiveIrpOffset >= This->ActiveIrpBufferSize) - { - This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE); - if (KeGetCurrentIrql() > DISPATCH_LEVEL) + + Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize); + if (!NT_SUCCESS(Status)) + { + This->RetryCount++; + if (This->RetryCount > 30) { - This->DelayedRequestInProgress = TRUE; - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); + DPRINT1("Stopping\n"); + This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); + This->RetryCount = 0; return; } - else + DPRINT("IServiceSink_fnRequestService> Waiting for mapping\n"); + This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); + return; + } + This->RetryCount = 0; + + if (KeGetCurrentIrql() == DISPATCH_LEVEL) + return; + + + Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position); + DPRINT("Position %u BufferSize %u ActiveIrpOffset %u\n", Position, This->CommonBufferSize, BufferSize); + + + if (Position < This->CommonBufferOffset) + { + BufferLength = This->CommonBufferSize - This->CommonBufferOffset; + + BytesToCopy = min(BufferLength, BufferSize); + + DPRINT("Copying %u\n", BytesToCopy); + + if (BytesToCopy) { - if (This->ActiveIrp) - { - This->ActiveIrp->IoStatus.Status = STATUS_SUCCESS; - This->ActiveIrp->IoStatus.Information = This->ActiveIrpBufferSize; - IoCompleteRequest(This->ActiveIrp, IO_SOUND_INCREMENT); - This->ActiveIrp = NULL; - } - - Status = IPortWaveCyclic_fnProcessNewIrp(This); - if (Status == STATUS_SUCCESS) - This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN); - else - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); + This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, Buffer, BytesToCopy); + This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy); + This->CommonBufferOffset = 0; + } + + + Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize); + if (!NT_SUCCESS(Status)) + { + DPRINT("IServiceSink_fnRequestService> Waiting for mapping\n"); + This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); + This->RetryCount++; return; } - } - - if (!This->ActiveIrp) - { - if (KeGetCurrentIrql() > DISPATCH_LEVEL) - { - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); - return; - } - - Status = IPortWaveCyclic_fnProcessNewIrp(This); - if (Status == STATUS_SUCCESS) - This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN); - else - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); - return; - } - - Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position); - DPRINT("Position %u BufferSize %u ActiveIrpOffset %u\n", Position, This->CommonBufferSize, This->ActiveIrpOffset); - - if (Position < This->CommonBufferOffset) - { - BufferLength = This->CommonBufferSize - This->CommonBufferOffset; - IrpLength = This->ActiveIrpBufferSize - This->ActiveIrpOffset; - - BytesToCopy = min(BufferLength, IrpLength); - - DPRINT("Copying %u Remaining %u\n", BytesToCopy, IrpLength); + + BytesToCopy = min(Position, BufferSize); + + DPRINT("Copying %u\n", BytesToCopy);
if (BytesToCopy) { - This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, (PUCHAR)This->ActiveIrpBuffer + This->ActiveIrpOffset, BytesToCopy); - This->ActiveIrpOffset += BytesToCopy; - This->CommonBufferOffset = 0; - } - else - { - This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE); - return; - } - BufferLength = Position; - IrpLength = This->ActiveIrpBufferSize - This->ActiveIrpOffset; - BytesToCopy = min(BufferLength, IrpLength); - - DPRINT("Copying %u Remaining %u\n", BytesToCopy, IrpLength); - - if (BytesToCopy) - { - This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)(PUCHAR)This->CommonBuffer, (PUCHAR)This->ActiveIrpBuffer + This->ActiveIrpOffset, BytesToCopy); - This->ActiveIrpOffset += Position; + This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)(PUCHAR)This->CommonBuffer, Buffer, BytesToCopy); + This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy); This->CommonBufferOffset = Position; }
@@ -190,23 +172,16 @@ else if (Position >= This->CommonBufferOffset) { BufferLength = Position - This->CommonBufferOffset; - IrpLength = This->ActiveIrpBufferSize - This->ActiveIrpOffset; - - BytesToCopy = min(BufferLength, IrpLength); - DPRINT("Copying %u Remaining %u\n", BytesToCopy, IrpLength); - - if (!BytesToCopy) - { - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); - return; - } - - This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, + + BytesToCopy = min(BufferLength, BufferSize); + DPRINT("Copying %u\n", BytesToCopy); + + This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, - (PUCHAR)This->ActiveIrpBuffer + This->ActiveIrpOffset, + Buffer, BytesToCopy);
- This->ActiveIrpOffset += BytesToCopy; + This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesToCopy); This->CommonBufferOffset = Position; }
@@ -299,44 +274,6 @@
NTSTATUS NTAPI -IPortWaveCyclic_fnProcessNewIrp( - IPortPinWaveCyclicImpl * This) -{ - PIO_STACK_LOCATION IoStack; - PKSSTREAM_HEADER Header; - - This->ActiveIrp = KsRemoveIrpFromCancelableQueue(&This->QueueHead, &This->QueueLock, KsListEntryTail, KsAcquireAndRemove); - if (!This->ActiveIrp) - { - This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L); - return STATUS_PENDING; - } - - DPRINT("ActiveIrp %p\n", This->ActiveIrp); - - IoStack = IoGetCurrentIrpStackLocation(This->ActiveIrp); - - if (IoStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(KSSTREAM_HEADER)) - { - DPRINT1("Irp has unexpected header\n"); - IoCompleteRequest(This->ActiveIrp, IO_NO_INCREMENT); - This->ActiveIrp = NULL; - return STATUS_INVALID_PARAMETER; - } - - Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; - DPRINT("Header %p Size %u\n", Header, Header->Size); - - - This->ActiveIrpOffset = 0; - This->ActiveIrpBuffer = Header->Data; - This->ActiveIrpBufferSize = Header->DataUsed; - - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI IPortPinWaveCyclic_HandleKsProperty( IN IPortPinWaveCyclic * iface, IN PIRP Irp) @@ -381,28 +318,9 @@ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; if (This->Stream) { - This->CommonBufferOffset = 0; - This->CommonBufferSize = This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel); - This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel); - - This->ActiveIrp = KsRemoveIrpFromCancelableQueue(&This->QueueHead, &This->QueueLock, KsListEntryHead, KsAcquireAndRemove); - if (This->ActiveIrp) - { - Status = IPortWaveCyclic_fnProcessNewIrp(This); - DPRINT1("IPortWaveCyclic_fnProcessNewIrp result %x\n", Status); - if (NT_SUCCESS(Status)) - { - //FIXME - // verify offset - resume stream - This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, This->CommonBuffer, This->ActiveIrpBuffer, This->CommonBufferSize); - This->ActiveIrpOffset += This->CommonBufferSize; - } - } - - Status = This->Stream->lpVtbl->SetState(This->Stream, *State);
- DPRINT1("Setting state %x\n", Status); + DPRINT1("Setting state %u %x\n", *State, Status); if (NT_SUCCESS(Status)) { This->State = *State; @@ -502,25 +420,10 @@ IN IPortPinWaveCyclic * iface, IN PIRP Irp) { - PIO_STACK_LOCATION IoStack; IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
- IoStack = IoGetCurrentIrpStackLocation(Irp); - - DPRINT1("IPortPinWaveCyclic_HandleKsStream entered\n"); - - if (!This->Stream) - { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - KsAddIrpToCancelableQueue(&This->QueueHead, &This->QueueLock, Irp, KsListEntryTail, NULL); - IoMarkIrpPending(Irp); - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_PENDING; + DPRINT1("IPortPinWaveCyclic_HandleKsStream entered State %u Stream %p\n", This->State, This->Stream); + DbgBreakPoint();
return STATUS_PENDING; } @@ -720,7 +623,30 @@ OUT PIO_STATUS_BLOCK StatusBlock, IN PDEVICE_OBJECT DeviceObject) { - return STATUS_SUCCESS; + NTSTATUS Status; + PCONTEXT_WRITE Packet; + IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface; + + DPRINT1("IPortPinWaveCyclic_fnFastWrite entered\n"); + + Packet = (PCONTEXT_WRITE)Buffer; + + + Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Packet->Irp); + + if (!NT_SUCCESS(Status)) + return FALSE; + + if ((This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) > This->IrpQueue->lpVtbl->MinMappings(This->IrpQueue)) && + This->State != KSSTATE_RUN) + { + /* some should initiate a state request but didnt do it */ + DPRINT1("Starting stream with %lu mappings\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue)); + This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN); + This->State = KSSTATE_RUN; + } + + return TRUE; }
/* @@ -737,6 +663,7 @@ { NTSTATUS Status; PKSDATAFORMAT DataFormat; + PDEVICE_OBJECT DeviceObject; IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
Port->lpVtbl->AddRef(Port); @@ -746,8 +673,15 @@ This->Filter = Filter; This->KsPinDescriptor = KsPinDescriptor; This->Miniport = GetWaveCyclicMiniport(Port); - KeInitializeSpinLock(&This->QueueLock); - InitializeListHead(&This->QueueHead); + + DeviceObject = GetDeviceObject(Port); + + + Status = NewIrpQueue(&This->IrpQueue); + if (!NT_SUCCESS(Status)) + return Status; + + Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DeviceObject);
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
@@ -784,6 +718,10 @@ This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
This->State = KSSTATE_STOP; + This->CommonBufferOffset = 0; + This->CommonBufferSize = This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel); + This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel); +
return STATUS_SUCCESS; }
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -718,6 +718,14 @@ return This->pMiniport; }
+PDEVICE_OBJECT +GetDeviceObject( + PPORTWAVECYCLIC iface) +{ + IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl *)iface; + return This->pDeviceObject; +} + //--------------------------------------------------------------- // IPortWaveCyclic constructor //
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -20,6 +20,7 @@ <file>filter_wavecyclic.c</file> <file>guids.c</file> <file>irp.c</file> + <file>irpstream.c</file> <file>interrupt.c</file> <file>drm.c</file> <file>stubs.c</file>
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -112,6 +112,11 @@ NTSTATUS StringFromCLSID( const CLSID *id, LPWSTR idstr); + +NTSTATUS +NTAPI +NewIrpQueue( + IN IIrpQueue **Queue);
typedef struct @@ -162,6 +167,12 @@
} PCLASS_DEVICE_EXTENSION, *PPCLASS_DEVICE_EXTENSION;
+ +typedef struct +{ + KSSTREAM_HEADER Header; + PIRP Irp; +}CONTEXT_WRITE, *PCONTEXT_WRITE;
NTSTATUS NTAPI @@ -226,5 +237,8 @@ IN PIRP Irp, IN PSUBDEVICE_DESCRIPTOR Descriptor);
+PDEVICE_OBJECT +GetDeviceObject( + IPortWaveCyclic* iface);
#endif
Modified: trunk/reactos/drivers/wdm/audio/drivers/directory.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/drivers/d... ============================================================================== --- trunk/reactos/drivers/wdm/audio/drivers/directory.rbuild [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/drivers/directory.rbuild [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -4,6 +4,10 @@ <directory name="mpu401"> <xi:include href="mpu401/mpu401.rbuild" /> </directory> + <directory name="CMIDriver"> + <xi:include href="CMIDriver/cmidriver.rbuild" /> + </directory> + <!--directory name="sb16"> <xi:include href="sb16/sb16.rbuild" /> </directory-->
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- 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] Fri Mar 6 22:06:21 2009 @@ -330,8 +330,8 @@ } } } - else - DPRINT1("KSPROPERTY_PIN_CTYPES index %u failed with %x\n", Index, Status); + else + DPRINT1("KSPROPERTY_PIN_CTYPES index %u failed with %x\n", Index, Status); }
@@ -357,6 +357,8 @@ ULONG BytesReturned; PFILE_OBJECT FileObject;
+ DPRINT1("WdmAudControlDeviceState\n"); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { @@ -393,90 +395,6 @@
ExFreePool(Context); return STATUS_SUCCESS; -} - -NTSTATUS -WdmAudControlWriteData( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo) -{ - PKSSTREAM_HEADER Packet; - NTSTATUS Status = STATUS_SUCCESS; - PFILE_OBJECT FileObject; - PWRITE_CONTEXT Context; - ULONG BytesReturned; - PUCHAR Buffer; - - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid buffer handle %x\n", DeviceInfo->hDevice); - return SetIrpIoStatus(Irp, Status, 0); - } - - if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE) - { - DPRINT1("FIXME: only waveout devices are supported\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - _SEH2_TRY - { - ProbeForRead(DeviceInfo->Buffer, DeviceInfo->BufferSize, TYPE_ALIGNMENT(char)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* Exception, get the error code */ - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid buffer supplied\n"); - return SetIrpIoStatus(Irp, Status, 0); - } - - Buffer = ExAllocatePool(NonPagedPool, DeviceInfo->BufferSize); - if (!Buffer) - { - /* no memory */ - return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); - } - - RtlMoveMemory(Buffer, DeviceInfo->Buffer, DeviceInfo->BufferSize); - - - Context = ExAllocatePool(NonPagedPool, sizeof(WRITE_CONTEXT)); - if (!Context) - { - /* no memory */ - return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); - } - - /* setup completion context */ - Context->Irp = Irp; - Context->Length = DeviceInfo->BufferSize; - - /* setup stream context */ - Packet = (PKSSTREAM_HEADER)ExAllocatePool(NonPagedPool, sizeof(KSSTREAM_HEADER)); - Packet->Data = Buffer; - Packet->FrameExtent = DeviceInfo->BufferSize; - Packet->DataUsed = DeviceInfo->BufferSize; - Packet->Size = sizeof(KSSTREAM_HEADER); - Packet->PresentationTime.Numerator = 1; - Packet->PresentationTime.Denominator = 1; - ASSERT(FileObject->FsContext != NULL); - - - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM, (PVOID)Packet, sizeof(KSSTREAM_HEADER), NULL, 0, &BytesReturned); - - DPRINT1("KsSynchronousIoControlDevice result %x\n", Status); - ExFreePool(Buffer); - - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); }
ULONG @@ -700,8 +618,6 @@ return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_SETDEVICE_STATE: return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_WRITEDATA: - return WdmAudControlWriteData(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_GETCAPABILITIES: return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); case IOCTL_CLOSE_WDMAUD: @@ -716,3 +632,112 @@
return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); } + +NTSTATUS +NTAPI +WdmAudWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_CLIENT ClientInfo; + NTSTATUS Status = STATUS_SUCCESS; + PUCHAR Buffer; + PCONTEXT_WRITE Packet; + PFILE_OBJECT FileObject; + IO_STATUS_BLOCK IoStatusBlock; + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT1("WdmAudWrite entered\n"); + + if (IoStack->Parameters.Write.Length < sizeof(WDMAUD_DEVICE_INFO)) + { + /* invalid parameter */ + DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.Write.Length, sizeof(WDMAUD_DEVICE_INFO)); + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + DeviceInfo = (PWDMAUD_DEVICE_INFO)MmGetMdlVirtualAddress(Irp->MdlAddress); + + + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Invalid buffer handle %x\n", DeviceInfo->hDevice); + return SetIrpIoStatus(Irp, Status, 0); + } + + + DPRINT1("DeviceInfo %p %p %p\n", DeviceInfo, Irp->MdlAddress->StartVa, Irp->MdlAddress->MappedSystemVa); + if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE) + { + /* invalid parameter */ + DPRINT1("Error: device type not set\n"); + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + if (!IoStack->FileObject) + { + /* file object parameter */ + DPRINT1("Error: file object is not attached\n"); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; + + + /* setup stream context */ + Packet = (PCONTEXT_WRITE)ExAllocatePool(NonPagedPool, sizeof(CONTEXT_WRITE)); + if (!Packet) + { + /* no memory */ + return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); + } + + Packet->Header.FrameExtent = DeviceInfo->BufferSize; + Packet->Header.DataUsed = DeviceInfo->BufferSize; + Packet->Header.Size = sizeof(KSSTREAM_HEADER); + Packet->Header.PresentationTime.Numerator = 1; + Packet->Header.PresentationTime.Denominator = 1; + Packet->Irp = Irp; + + Buffer = ExAllocatePool(NonPagedPool, DeviceInfo->BufferSize); + if (!Buffer) + { + /* no memory */ + ExFreePool(Packet); + return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); + } + Packet->Header.Data = Buffer; + + _SEH2_TRY + { + ProbeForRead(DeviceInfo->Buffer, DeviceInfo->BufferSize, TYPE_ALIGNMENT(char)); + RtlMoveMemory(Buffer, DeviceInfo->Buffer, DeviceInfo->BufferSize); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Exception, get the error code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Invalid buffer supplied\n"); + ExFreePool(Buffer); + ExFreePool(Packet); + return SetIrpIoStatus(Irp, Status, 0); + } + + KsStreamIo(FileObject, NULL, NULL, NULL, NULL, 0, &IoStatusBlock, Packet, sizeof(CONTEXT_WRITE), KSSTREAM_WRITE, KernelMode); + + Irp->IoStatus.Status = STATUS_PENDING; + Irp->IoStatus.Information = 0; + IoMarkIrpPending(Irp); + return STATUS_PENDING; + + //return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); +} +
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c [iso-8859-1] Fri Mar 6 22:06:21 2009 @@ -247,6 +247,7 @@ Driver->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp; Driver->MajorFunction[IRP_MJ_CLEANUP] = WdmAudCleanup; Driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WdmAudDeviceControl; + Driver->MajorFunction[IRP_MJ_WRITE] = WdmAudWrite; Driver->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
return WdmAudInstallDevice(Driver);
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- 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] Fri Mar 6 22:06:21 2009 @@ -43,6 +43,13 @@
typedef struct { + KSSTREAM_HEADER Header; + PIRP Irp; +}CONTEXT_WRITE, *PCONTEXT_WRITE; + + +typedef struct +{ PIRP Irp; IO_STATUS_BLOCK StatusBlock; ULONG Length; @@ -70,4 +77,11 @@ IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS +NTAPI +WdmAudWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + #endif
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] Fri Mar 6 22:06:21 2009 @@ -97,10 +97,10 @@ ASSERT(Context);
Status = KsSynchronousIoControlDevice(Context->FileObject, KernelMode, IOCTL_KS_WRITE_STREAM, - IoStack->Parameters.DeviceIoControl.Type3InputBuffer, - IoStack->Parameters.DeviceIoControl.InputBufferLength, - Irp->UserBuffer, - IoStack->Parameters.DeviceIoControl.OutputBufferLength, + MmGetMdlVirtualAddress(Irp->MdlAddress), + IoStack->Parameters.Write.Length, + NULL, + 0, &BytesReturned);
Irp->IoStatus.Information = BytesReturned; @@ -216,9 +216,16 @@ PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { + PDISPATCH_CONTEXT Context; + NTSTATUS Status; DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
- return FALSE; + Context = (PDISPATCH_CONTEXT)FileObject->FsContext2; + Status = KsStreamIo(Context->FileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode); + if (Status == STATUS_SUCCESS) + return TRUE; + else + return FALSE; }
static KSDISPATCH_TABLE PinTable =