Author: janderwald Date: Wed Nov 3 11:16:33 2010 New Revision: 49457
URL: http://svn.reactos.org/svn/reactos?rev=49457&view=rev Log: [KS] - Fix several bugs in KsProbeStreamIrp - If requestor is KernelMode - just save a pointer in Irp->AssociatedIrp.SystemBuffer (currently not used) - If requestor is UserMode mark irp as buffered. Also set Flag IRP_INPUT_OPERATION when the ioctl is IOCTL_KS_READ_STREAM. This is important to propagate modifications to KSSTREAM_HEADERS (in particular DataUsed member) - ReactOS KS can now be used in WinXP in combination with KSStudio. In order to make it fully work, ks needs to implement software bus functions [PORTCLS] - Rewrite internal irp queue handling - It now supports multiple KSSTREAM_HEADERs per Irp, variable sized KSSTREAM_HEADERs per irp. - Store the mapped virtual address not in the KSSTREAM_HEADER, as user programs will receive then invalid addresses - Add checks whether this irp is for an sink pin or source pin - Fix multiple bugs when the pin is looped buffer mode (How did this work before?) - ReactOS portcls + WinXP now properly works with audio recording [WDMAUD_KERNEL] - Don't free associated stream header anymore - Tested with VBox 3.2.10 + VmWare Player 3.1.2 + WinXP
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c trunk/reactos/drivers/ksfilter/ks/topology.c trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.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] Wed Nov 3 11:16:33 2010 @@ -661,6 +661,11 @@
if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer) { + if (Irp->RequestorMode == KernelMode) + { + /* no need to allocate stream header */ + Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer; + } AllocMdl: /* check if alloc mdl flag is passed */ if (!(ProbeFlags & KSPROBE_ALLOCATEMDL)) @@ -910,6 +915,9 @@ return STATUS_INSUFFICIENT_RESOURCES; }
+ /* mark irp as buffered so that changes the stream headers are propagated back */ + Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; + _SEH2_TRY { if (ProbeFlags & KSPROBE_STREAMWRITE) @@ -923,6 +931,9 @@ { /* stream reads means writing */ ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); + + /* set input operation flags */ + Irp->Flags |= IRP_INPUT_OPERATION; }
/* copy stream buffer */
Modified: trunk/reactos/drivers/ksfilter/ks/topology.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/topolog... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/topology.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/topology.c [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -38,7 +38,7 @@ return STATUS_INSUFFICIENT_RESOURCES; }
- /* build a request which looks like {ObjectClass}\CreateParameters + /* build a request which looks like {ObjectClass}\CreateParameters * For pins the parent is the reference string used in registration * For clocks it is full path for pin{ClockGuid}\ClockCreateParams */
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -319,9 +319,11 @@ DEFINE_ABSTRACT_UNKNOWN()
STDMETHOD_(NTSTATUS, Init)(THIS_ - IN KSPIN_CONNECT *ConnectDetails, + IN PKSPIN_CONNECT ConnectDetails, + IN PKSPIN_DESCRIPTOR Descriptor, IN ULONG FrameSize, - IN ULONG Alignment) PURE; + IN ULONG Alignment, + IN ULONG TagSupportEnabled) PURE;
STDMETHOD_(NTSTATUS, AddMapping)(THIS_ IN PIRP Irp, @@ -360,9 +362,11 @@
#define IMP_IIrpQueue \ STDMETHODIMP_(NTSTATUS) Init(THIS_ \ - IN KSPIN_CONNECT *ConnectDetails, \ + IN PKSPIN_CONNECT ConnectDetails, \ + IN PKSPIN_DESCRIPTOR Descriptor, \ IN ULONG FrameSize, \ - IN ULONG Alignment); \ + IN ULONG Alignment, \ + IN ULONG TagSupportEnabled); \ \ STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \ IN PIRP Irp, \
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -35,31 +35,40 @@ virtual ~CIrpQueue(){}
protected: - volatile ULONG m_CurrentOffset; - LONG m_NumMappings; - ULONG m_NumDataAvailable; + PKSPIN_CONNECT m_ConnectDetails; + PKSPIN_DESCRIPTOR m_Descriptor; + KSPIN_LOCK m_IrpListLock; LIST_ENTRY m_IrpList; LIST_ENTRY m_FreeIrpList; - PIRP m_Irp;
ULONG m_OutOfMapping; ULONG m_MaxFrameSize; ULONG m_Alignment; + ULONG m_TagSupportEnabled; + ULONG m_NumDataAvailable; + volatile ULONG m_CurrentOffset; + + PIRP m_Irp; +
LONG m_Ref;
};
-#define OFFSET_HEADERINDEX (0) -#define OFFSET_STREAMHEADER (2) -#define OFFSET_HEADERCOUNT (3) - - -#define STREAMHEADER_INDEX(Irp) (PtrToUlong(Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX])) -#define STREAMHEADER_COUNT(Irp) (PtrToUlong(Irp->Tail.Overlay.DriverContext[OFFSET_HEADERCOUNT])) -#define STREAMHEADER_CURRENT(Irp) (Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER]) +typedef struct +{ + ULONG StreamHeaderCount; + ULONG StreamHeaderIndex; + ULONG TotalStreamData; + + PKSSTREAM_HEADER CurStreamHeader; + PVOID * Data; + PVOID * Tags; +}KSSTREAM_DATA, *PKSSTREAM_DATA; + +#define STREAM_DATA_OFFSET (0)
NTSTATUS @@ -81,13 +90,17 @@ NTSTATUS NTAPI CIrpQueue::Init( - IN KSPIN_CONNECT *ConnectDetails, + IN PKSPIN_CONNECT ConnectDetails, + IN PKSPIN_DESCRIPTOR Descriptor, IN ULONG FrameSize, - IN ULONG Alignment) + IN ULONG Alignment, + IN ULONG TagSupportEnabled) { m_ConnectDetails = ConnectDetails; + m_Descriptor = Descriptor; m_MaxFrameSize = FrameSize; m_Alignment = Alignment; + m_TagSupportEnabled = TagSupportEnabled;
InitializeListHead(&m_IrpList); InitializeListHead(&m_FreeIrpList); @@ -103,110 +116,158 @@ OUT PULONG Data) { PKSSTREAM_HEADER Header; - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION IoStack; - ULONG NumHeaders, NumData, Index; + ULONG Index, Length; PMDL Mdl; + PKSSTREAM_DATA StreamData;
PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + + // allocate stream data + StreamData = (PKSSTREAM_DATA)AllocateItem(NonPagedPool, sizeof(KSSTREAM_DATA), TAG_PORTCLASS); + if (!StreamData) + { + // not enough memory + return STATUS_INSUFFICIENT_RESOURCES; + }
// get current irp stack location IoStack = IoGetCurrentIrpStackLocation(Irp);
- if (!Irp->MdlAddress) - { - // ioctl from KsStudio - // Wdmaud already probes buffers, therefore no need to probe it again - // probe the stream irp - if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) - Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); - else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) - Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); - else - PC_ASSERT(0); - - // check for success - if (!NT_SUCCESS(Status)) - { - DPRINT("KsProbeStreamIrp failed with %x\n", Status); - return Status; - } + // lets probe the irp + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) + { + // probe IOCTL_KS_WRITE_STREAM + Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); + } + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) + { + // probe IOCTL_KS_READ_STREAM + Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); + } + + // check for success + if (!NT_SUCCESS(Status)) + { + // irp probing failed + FreeItem(StreamData, TAG_PORTCLASS); + return Status; }
// get first stream header - - if (Irp->RequestorMode == UserMode) - Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; - else - Header = (PKSSTREAM_HEADER)Irp->UserBuffer; + Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + // store header + StreamData->CurStreamHeader = Header;
// sanity check PC_ASSERT(Header);
- // calculate num headers - NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size; - - // assume headers of same length - PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0); - - - // get first audio buffer + // first calculate the numbers of stream headers + Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + + do + { + /* subtract size */ + Length -= Header->Size; + + /* increment header count */ + StreamData->StreamHeaderCount++; + + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // irp sink + StreamData->TotalStreamData += Header->DataUsed; + } + else + { + // irp source + StreamData->TotalStreamData += Header->FrameExtent; + } + + /* move to next header */ + Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size); + + }while(Length); + + // sanity check + ASSERT(StreamData->StreamHeaderCount); + + // allocate array for storing the pointers of the data */ + StreamData->Data = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) * StreamData->StreamHeaderCount, TAG_PORTCLASS); + if (!StreamData->Data) + { + // out of memory + FreeItem(StreamData, TAG_PORTCLASS); + + // done + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (m_TagSupportEnabled) + { + // allocate array for storing the pointers of the data */ + StreamData->Tags = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) * StreamData->StreamHeaderCount, TAG_PORTCLASS); + if (!StreamData->Data) + { + // out of memory + FreeItem(StreamData->Data, TAG_PORTCLASS); + FreeItem(StreamData, TAG_PORTCLASS); + + // done + return STATUS_INSUFFICIENT_RESOURCES; + } + } + + + // now get a system address for the user buffers + Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; Mdl = Irp->MdlAddress; - // sanity check - PC_ASSERT(Mdl); - - // store the current stream header - Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER] = (PVOID)Header; - // store header count - Irp->Tail.Overlay.DriverContext[OFFSET_HEADERCOUNT] = UlongToPtr(NumHeaders); - - // store current header index - Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0); - - NumData = 0; - // prepare all headers - for(Index = 0; Index < NumHeaders; Index++) - { - // sanity checks - PC_ASSERT(Header); - PC_ASSERT(Mdl); - - if (Irp->RequestorMode == UserMode) - { - Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); - } - - if (!Header->Data) - { - // insufficient resources - ExFreePool(Irp->AssociatedIrp.SystemBuffer); - Irp->AssociatedIrp.SystemBuffer = NULL; - // complete and forget request - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); + + for(Index = 0; Index < StreamData->StreamHeaderCount; Index++) + { + /* get system address */ + StreamData->Data[Index] = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + + /* check for success */ + if (!StreamData->Data[Index]) + { + // out of resources + FreeItem(StreamData->Data, TAG_PORTCLASS); + + if (m_TagSupportEnabled) + { + // free tag array + FreeItem(StreamData->Tags, TAG_PORTCLASS); + } + + FreeItem(StreamData, TAG_PORTCLASS); + // done return STATUS_INSUFFICIENT_RESOURCES; }
- // increment num mappings - InterlockedIncrement(&m_NumMappings); - - // increment available data - InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, - (max(Header->DataUsed, Header->FrameExtent))); - - NumData += max(Header->DataUsed, Header->FrameExtent); - - // move to next header + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->DataUsed); + } + else if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT) + { + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->FrameExtent); + } + + // move to next header / mdl + Mdl = Mdl->Next; Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size); - - // move to next mdl - Mdl = Mdl->Next; - } - - DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable); - *Data = NumData; + + } + + // store stream data + Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET] = (PVOID)StreamData; + + *Data = StreamData->TotalStreamData;
// mark irp as pending IoMarkIrpPending(Irp); @@ -218,7 +279,7 @@ m_OutOfMapping = FALSE;
// done - return Status; + return STATUS_SUCCESS; }
NTSTATUS @@ -229,8 +290,7 @@ { PIRP Irp; ULONG Offset; - //PIO_STACK_LOCATION IoStack; - PKSSTREAM_HEADER StreamHeader; + PKSSTREAM_DATA StreamData;
// check if there is an irp in the partially processed if (m_Irp) @@ -247,6 +307,7 @@ m_Irp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(m_Irp, IO_NO_INCREMENT); m_Irp = Irp = NULL; + m_CurrentOffset = 0; } } else @@ -259,26 +320,32 @@ if (!Irp) { // no irp buffer available - DPRINT("NoIrp\n"); return STATUS_UNSUCCESSFUL; }
- // get stream header - StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; - - // sanity check - PC_ASSERT(StreamHeader); - - // store buffersize - if (StreamHeader->DataUsed) - *BufferSize = StreamHeader->DataUsed - Offset; + // get stream data + StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + // sanity check + PC_ASSERT(StreamData); + + // get buffer size + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // sink pin + *BufferSize = StreamData->CurStreamHeader->DataUsed - Offset; + } else - *BufferSize = StreamHeader->FrameExtent - Offset; - + { + // source pin + *BufferSize = StreamData->CurStreamHeader->FrameExtent - Offset; + } + + // sanity check PC_ASSERT(*BufferSize);
// store buffer - *Buffer = &((PUCHAR)StreamHeader->Data)[Offset]; + *Buffer = &((PUCHAR)StreamData->Data[StreamData->StreamHeaderIndex])[Offset];
// unset flag that no irps are available m_OutOfMapping = FALSE; @@ -291,102 +358,111 @@ CIrpQueue::UpdateMapping( IN ULONG BytesWritten) { - PKSSTREAM_HEADER StreamHeader; - ULONG Size, NumData, Index; - - if (!m_Irp) - { - // silence buffer was used - return; - } - - // get stream header - StreamHeader = (PKSSTREAM_HEADER)STREAMHEADER_CURRENT(m_Irp); - - // sanity check - // ASSERT(StreamHeader); + PKSSTREAM_DATA StreamData; + ULONG Size; + PIO_STACK_LOCATION IoStack; + + // sanity check + ASSERT(m_Irp); + + // get stream data + StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + // sanity check + ASSERT(StreamData);
// add to current offset InterlockedExchangeAdd((volatile PLONG)&m_CurrentOffset, (LONG)BytesWritten);
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT) + { + // store written bytes (source pin) + StreamData->CurStreamHeader->DataUsed += BytesWritten; + } + // decrement available data counter m_NumDataAvailable -= BytesWritten;
- if (StreamHeader->DataUsed) - Size = StreamHeader->DataUsed; + // get audio buffer size + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT) + Size = StreamData->CurStreamHeader->FrameExtent; else - Size = StreamHeader->FrameExtent; - + Size = StreamData->CurStreamHeader->DataUsed; + + // sanity check PC_ASSERT(Size);
if (m_CurrentOffset >= Size) { - if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp)) - { - // the irp has at least one more stream header - m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1); - - // get next stream header - StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); - - // store next stream header - STREAMHEADER_CURRENT(m_Irp) = (PVOID)StreamHeader; - - // reset current offset + // sanity check + PC_ASSERT(Size == m_CurrentOffset); + + if (StreamData->StreamHeaderIndex + 1 < StreamData->StreamHeaderCount) + { + // move to next stream header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader + StreamData->CurStreamHeader->Size); + + // increment stream header index + StreamData->StreamHeaderIndex++; + + // reset offset m_CurrentOffset = 0;
// done return; }
- // irp has been processed completly - NumData = 0; - if (m_Irp->RequestorMode == KernelMode) - StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer; - else - StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer; - - // loop all stream headers - for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++) - { - PC_ASSERT(StreamHeader); - - // add size of buffer - // depends on if the buffer is input / output - if (StreamHeader->DataUsed) - Size = StreamHeader->DataUsed; - else - Size = StreamHeader->FrameExtent; - - // increment size - NumData += Size; - - // get next stream header - StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); - } - + // + // all stream buffers have been played + // check if this is a looped buffer + // if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) { // looped streaming repeat the buffers untill // the caller decides to stop the streams
// reset stream header index - m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0); + StreamData->StreamHeaderIndex = 0; + + // reset stream header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer; + + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, StreamData->TotalStreamData); + // re-insert irp KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL); + // clear current irp m_Irp = NULL; + // reset offset m_CurrentOffset = 0; - // increment available data - InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, NumData); + // done return; }
+ // free stream data array + FreeItem(StreamData->Data, TAG_PORTCLASS); + + if (m_TagSupportEnabled) + { + // free tag array + FreeItem(StreamData->Tags, TAG_PORTCLASS); + } + + // free stream data + FreeItem(StreamData, TAG_PORTCLASS); + + // get io stack + IoStack = IoGetCurrentIrpStackLocation(m_Irp); + // store operation status m_Irp->IoStatus.Status = STATUS_SUCCESS; - m_Irp->IoStatus.Information = 0; + + // store operation length + m_Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
// complete the request IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT); @@ -411,6 +487,8 @@ NTAPI CIrpQueue::CancelBuffers() { + //TODO: own cancel routine + // is there an active irp if (m_Irp) { @@ -422,8 +500,7 @@
// cancel all irps KsCancelIo(&m_IrpList, &m_IrpListLock); - // reset number of mappings - m_NumMappings = 0; + // reset number of data available m_NumDataAvailable = 0;
@@ -440,44 +517,83 @@ OUT PULONG ByteCount, OUT PULONG Flags) { - PKSSTREAM_HEADER StreamHeader; - PIRP Irp; - - *Flags = 0; + PKSSTREAM_DATA StreamData; + + /* sanity checks */ PC_ASSERT(Tag != NULL); - - // get an irp from the queue - Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + PC_ASSERT(PhysicalAddress); + PC_ASSERT(VirtualAddress); + PC_ASSERT(ByteCount); + PC_ASSERT(Flags); + + if (!m_Irp) + { + // get an irp from the queue + m_Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + }
// check if there is an irp - if (!Irp) + if (!m_Irp) { // no irp available m_OutOfMapping = TRUE; return STATUS_NOT_FOUND; }
- //FIXME support more than one stream header - PC_ASSERT(STREAMHEADER_COUNT(Irp) == 1); - - // HACK get stream header - StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; - - // store mapping in the free list - ExInterlockedInsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry, &m_IrpListLock); - - // return mapping - *PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data); - *VirtualAddress = StreamHeader->Data; - *ByteCount = StreamHeader->DataUsed; - - // decrement mapping count - InterlockedDecrement(&m_NumMappings); - // decrement num data available - m_NumDataAvailable -= StreamHeader->DataUsed; + // get stream data + StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + // sanity check + PC_ASSERT(StreamData->StreamHeaderIndex < StreamData->StreamHeaderCount); + + // setup mapping + *PhysicalAddress = MmGetPhysicalAddress(StreamData->Data[StreamData->StreamHeaderIndex]); + *VirtualAddress = StreamData->Data[StreamData->StreamHeaderIndex];
// store tag in irp - Irp->Tail.Overlay.DriverContext[3] = Tag; + StreamData->Tags[StreamData->StreamHeaderIndex] = Tag; + + // mapping size + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // sink pin + *ByteCount = StreamData->CurStreamHeader->DataUsed; + + // decrement num data available + m_NumDataAvailable -= StreamData->CurStreamHeader->DataUsed; + } + else + { + // source pin + *ByteCount = StreamData->CurStreamHeader->FrameExtent; + + // decrement num data available + m_NumDataAvailable -= StreamData->CurStreamHeader->FrameExtent; + } + + if (StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount) + { + // last mapping + *Flags = 1; + + // insert mapping into free list + ExInterlockedInsertTailList(&m_FreeIrpList, &m_Irp->Tail.Overlay.ListEntry, &m_IrpListLock); + + // clear irp + m_Irp = NULL; + + } + else + { + // one more mapping in the irp + *Flags = 0; + + // increment header index + StreamData->StreamHeaderIndex++; + + // move to next header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader + StreamData->CurStreamHeader->Size); + }
// done return STATUS_SUCCESS; @@ -490,34 +606,123 @@ { PIRP Irp; PLIST_ENTRY CurEntry; - PKSSTREAM_HEADER StreamHeader; - - DPRINT("CIrpQueue::ReleaseMappingWithTag Tag %p\n", Tag); + PKSSTREAM_DATA StreamData; + PIO_STACK_LOCATION IoStack; + ULONG Index; + + // first check if there is an active irp + if (m_Irp) + { + // now check if there are already used mappings + StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + if (StreamData->StreamHeaderIndex) + { + // check if the released mapping is one current processed irps + for(Index = 0; Index < StreamData->StreamHeaderIndex; Index++) + { + // check if it is the same tag + if (StreamData->Tags[Index] == Tag) + { + // mark mapping as released + StreamData->Tags[Index] = NULL; + + // done + return STATUS_SUCCESS; + } + + } + } + }
// remove irp from used list CurEntry = ExInterlockedRemoveHeadList(&m_FreeIrpList, &m_IrpListLock); + // sanity check PC_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 - PC_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; - - // complete the request - IoCompleteRequest(Irp, IO_SOUND_INCREMENT); + // get stream data + StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + // sanity check + PC_ASSERT(StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount); + + // check if the released mapping is one of these + for(Index = 0; Index < StreamData->StreamHeaderCount; Index++) + { + if (StreamData->Tags[Index] == Tag) + { + // mark mapping as released + StreamData->Tags[Index] = NULL; + + // done + break; + } + else + { + // + // we assume that mappings are released in the same order as they have been acquired + // therefore if the current mapping is not the searched one, it must have been already + // released + // + PC_ASSERT(StreamData->Tags[Index] == NULL); + } + } + + // check if this is the last one released mapping + if (Index + 1 == StreamData->StreamHeaderCount) + { + // last mapping released + // now check if this is a looped buffer + if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) + { + // looped buffers are not completed when they have been played + // they are completed when the stream is set to stop + + // reset stream header index + StreamData->StreamHeaderIndex = 0; + + // reset stream header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, StreamData->TotalStreamData); + + // re-insert irp + KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, Irp, KsListEntryTail, NULL); + + // done + return STATUS_SUCCESS; + } + + // + // time to complete non looped buffer + // + + // free stream data array + FreeItem(StreamData->Data, TAG_PORTCLASS); + + // free stream tags array + FreeItem(StreamData->Tags, TAG_PORTCLASS); + + // free stream data + FreeItem(StreamData, TAG_PORTCLASS); + + // get io stack + IoStack = IoGetCurrentIrpStackLocation(Irp); + + // store operation status + Irp->IoStatus.Status = STATUS_SUCCESS; + + // store operation length + Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + + // complete the request + IoCompleteRequest(Irp, IO_SOUND_INCREMENT); + }
return STATUS_SUCCESS; } @@ -545,38 +750,18 @@ { KIRQL OldLevel; BOOLEAN Ret = FALSE; - PIRP Irp; - PLIST_ENTRY CurEntry; - + //PIRP Irp; + //PLIST_ENTRY CurEntry; + //PKSSTREAM_DATA StreamData; + + // lock list KeAcquireSpinLock(&m_IrpListLock, &OldLevel);
- if (!IsListEmpty(&m_FreeIrpList)) - { - // get first entry - CurEntry = RemoveHeadList(&m_FreeIrpList); - // get irp from list entry - Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); - - // get tag of first acquired buffer - *FirstTag = Irp->Tail.Overlay.DriverContext[3]; - - // put back irp - InsertHeadList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry); - - // get last entry - CurEntry = RemoveTailList(&m_FreeIrpList); - // get irp from list entry - Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); - - // get tag of first acquired buffer - *LastTag = Irp->Tail.Overlay.DriverContext[3]; - - // put back irp - InsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry); - - // indicate success - Ret = TRUE; - } + // initialize to zero + *FirstTag = NULL; + *LastTag = NULL; + + UNIMPLEMENTED;
// release lock KeReleaseSpinLock(&m_IrpListLock, OldLevel);
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -604,7 +604,7 @@ } }
- Status = m_IrpQueue->Init(ConnectDetails, 0, 0); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE); if (!NT_SUCCESS(Status)) { DPRINT("IrpQueue_Init failed with %x\n", Status);
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -702,7 +702,7 @@ if (Gap > BufferLength) { // insert silence samples - DPRINT1("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength); + DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength); m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
m_CommonBufferOffset += BufferLength; @@ -761,7 +761,7 @@ if (Gap > BufferLength) { // insert silence samples - DPRINT1("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position); + DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position); m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
m_CommonBufferOffset += BufferLength; @@ -1303,7 +1303,7 @@
m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
- Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_FrameSize, 0, FALSE); if (!NT_SUCCESS(Status)) { m_IrpQueue->Release();
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -919,7 +919,7 @@ }
// initialize irp queue - Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE); if (!NT_SUCCESS(Status)) { // this should never happen
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp [iso-8859-1] Wed Nov 3 11:16:33 2010 @@ -283,7 +283,7 @@ CPortPinWaveRT::HandleKsStream( IN PIRP Irp) { - DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n", m_State, m_Stream); + DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p is UNIMPLEMENTED\n", m_State, m_Stream);
return STATUS_PENDING; } @@ -587,7 +587,7 @@ goto cleanup; }
- Status = m_IrpQueue->Init(ConnectDetails, 0, 0); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE); if (!NT_SUCCESS(Status)) { goto cleanup; @@ -624,7 +624,7 @@ // delay of 10 milisec m_Delay = Int32x32To64(10, -10000);
- Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType); + Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType); if (!NT_SUCCESS(Status)) { DPRINT("AllocateAudioBuffer failed with %x\n", Status);
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] Wed Nov 3 11:16:33 2010 @@ -452,15 +452,17 @@ /* now free the mdl */ IoFreeMdl(Context->Mdl);
- /* now free the stream header */ - ExFreePool(Irp->AssociatedIrp.SystemBuffer); - DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx Length %lu\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information, Length);
if (Irp->IoStatus.Status == STATUS_SUCCESS) { /* store the length */ Irp->IoStatus.Information = Length; + } + else + { + /* failed */ + Irp->IoStatus.Information = 0; }
/* free context */