typedef struct _IRP_MAPPING_
{
LIST_ENTRY Entry;
- KSSTREAM_HEADER *Header;
+ PVOID Buffer;
+ ULONG BufferSize;
+ ULONG OriginalBufferSize;
+ PVOID OriginalBuffer;
PIRP Irp;
- ULONG References;
- ULONG NumTags;
- PVOID * Tag;
+ PVOID Tag;
}IRP_MAPPING, *PIRP_MAPPING;
typedef struct
KSPIN_LOCK Lock;
LIST_ENTRY ListHead;
+ LIST_ENTRY FreeHead;
ULONG OutOfMapping;
ULONG MaxFrameSize;
if (CurMapping->Irp)
{
- CurMapping->Irp->IoStatus.Information = CurMapping->Header->FrameExtent;
+ CurMapping->Irp->IoStatus.Information = CurMapping->OriginalBufferSize;
CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT);
}
- if (CurMapping->Tag)
+ if (CurMapping->OriginalBuffer)
{
- FreeItem(CurMapping->Tag, TAG_PORTCLASS);
+ ExFreePool(CurMapping->OriginalBuffer);
}
- ExFreePool(CurMapping->Header->Data);
- ExFreePool(CurMapping->Header);
-
ExFreePool(CurMapping);
}
This->MaxFrameSize = FrameSize;
InitializeListHead(&This->ListHead);
+ InitializeListHead(&This->FreeHead);
KeInitializeSpinLock(&This->Lock);
return STATUS_SUCCESS;
IN ULONG BufferSize,
IN PIRP Irp)
{
- PIRP_MAPPING Mapping;
+ PIRP_MAPPING Mapping = NULL;
+ KSSTREAM_HEADER * Header = (KSSTREAM_HEADER*)Buffer;
+ ULONG Index, NumMappings, Offset;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
- Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
- if (!Mapping)
- return STATUS_UNSUCCESSFUL;
-
- Mapping->Header = (KSSTREAM_HEADER*)Buffer;
- Mapping->Irp = Irp;
if (This->MaxFrameSize)
{
- if (This->MaxFrameSize > Mapping->Header->DataUsed)
+ if (This->MaxFrameSize > Header->DataUsed)
{
/* small mapping */
- Mapping->NumTags = 1;
+ NumMappings = 1;
}
else
{
- ULONG Rest = Mapping->Header->DataUsed % This->MaxFrameSize;
+ ULONG Rest = Header->DataUsed % This->MaxFrameSize;
- Mapping->NumTags = Mapping->Header->DataUsed / This->MaxFrameSize;
+ NumMappings = Header->DataUsed / This->MaxFrameSize;
if (Rest)
{
- Mapping->NumTags++;
+ NumMappings++;
}
}
}
else
{
/* no framesize restriction */
- Mapping->NumTags = 1;
+ NumMappings = 1;
}
- Mapping->Tag = AllocateItem(NonPagedPool, sizeof(PVOID) * Mapping->NumTags, TAG_PORTCLASS);
- if (!Mapping->Tag)
+ for(Index = 0; Index < NumMappings; Index++)
{
- FreeItem(Mapping, TAG_PORTCLASS);
- return STATUS_UNSUCCESSFUL;
- }
- ASSERT(Mapping->NumTags < 32);
- Mapping->References = (1 << Mapping->NumTags) - 1;
+ Mapping = AllocateItem(NonPagedPool, sizeof(IRP_MAPPING), TAG_PORTCLASS);
+ if (!Mapping)
+ {
+ DPRINT("OutOfMemory\n");
+ return STATUS_UNSUCCESSFUL;
+ }
- This->NumDataAvailable += Mapping->Header->DataUsed;
+ if (Index)
+ Offset = Index * This->MaxFrameSize;
+ else
+ Offset = 0;
- DPRINT("IIrpQueue_fnAddMapping NumMappings %u SizeOfMapping %lu NumDataAvailable %lu Mapping %p NumTags %u References %x FrameSize %u\n", This->NumMappings, Mapping->Header->DataUsed, This->NumDataAvailable, Mapping, Mapping->NumTags, Mapping->References, This->MaxFrameSize);
+ Mapping->Buffer = (PVOID)UlongToPtr(PtrToUlong(Header->Data) + Offset);
- KeAcquireSpinLockAtDpcLevel(&This->Lock);
- InsertTailList(&This->ListHead, &Mapping->Entry);
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
+ if (This->MaxFrameSize)
+ Mapping->BufferSize = min(Header->DataUsed - Offset, This->MaxFrameSize);
+ else
+ Mapping->BufferSize = Header->DataUsed;
+
+ Mapping->OriginalBufferSize = Header->FrameExtent;
+ Mapping->OriginalBuffer = NULL;
+ Mapping->Irp = NULL;
+ Mapping->Tag = NULL;
+
+ This->NumDataAvailable += Mapping->BufferSize;
- (void)InterlockedIncrement((volatile long*)&This->NumMappings);
+ 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)
{
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
PLIST_ENTRY CurEntry;
- KeAcquireSpinLockAtDpcLevel(&This->Lock);
-
-
- CurEntry = This->ListHead.Flink;
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
- if (CurEntry == &This->ListHead)
+ CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
+ if (!CurEntry)
{
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
+ This->StartStream = FALSE;
This->OutOfMapping = TRUE;
return STATUS_UNSUCCESSFUL;
}
- *Buffer = (PUCHAR)CurMapping->Header->Data + This->CurrentOffset;
- *BufferSize = CurMapping->Header->DataUsed - This->CurrentOffset;
+ 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);
This->OutOfMapping = FALSE;
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
return STATUS_SUCCESS;
}
PIRP_MAPPING CurMapping;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
+ CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
+ CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
+
This->CurrentOffset += BytesWritten;
This->NumDataAvailable -= BytesWritten;
- CurEntry = This->ListHead.Flink;
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
-
- if (CurMapping->Header->DataUsed <= This->CurrentOffset)
+ if (CurMapping->BufferSize <= This->CurrentOffset)
{
This->CurrentOffset = 0;
-
- KeAcquireSpinLockAtDpcLevel(&This->Lock);
- RemoveHeadList(&This->ListHead);
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
-
InterlockedDecrement(&This->NumMappings);
FreeMappingRoutine(CurMapping);
}
-
+ else
+ {
+ ExInterlockedInsertHeadList(&This->ListHead, &CurMapping->Entry, &This->Lock);
+ }
}
ULONG
}
-VOID
-GetMapping(
- IIrpQueueImpl * This,
- IN ULONG Index,
- IN PVOID Tag,
- IN PIRP_MAPPING CurMapping,
- OUT PPHYSICAL_ADDRESS PhysicalAddress,
- OUT PVOID *VirtualAddress,
- OUT PULONG ByteCount,
- OUT PULONG Flags)
-{
- ULONG Offset;
-
- /* calculate the offset */
- if (Index)
- Offset = Index * This->MaxFrameSize;
- else
- Offset = 0;
-
- ASSERT(CurMapping->Header->DataUsed > Offset);
-
- *VirtualAddress = (PUCHAR)CurMapping->Header->Data + Offset;
- *PhysicalAddress = MmGetPhysicalAddress(*VirtualAddress);
- /* FIXME alignment */
- *ByteCount = min(CurMapping->Header->DataUsed - Offset, This->MaxFrameSize);
-
- /* reset out of mapping indicator */
- This->OutOfMapping = FALSE;
-
- /* decrement available byte counter */
- This->NumDataAvailable -= *ByteCount;
-
- /* store the tag */
- CurMapping->Tag[Index] = Tag;
-
- if (Index + 1 == CurMapping->NumTags)
- {
- /* indicate end of packet */
- *Flags = 1;
- }
-
- DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p Mapping %p Index %u NumTags %u\n", Tag, CurMapping, Index, CurMapping->NumTags);
-}
-
-
NTSTATUS
NTAPI
IIrpQueue_fnGetMappingWithTag(
{
PIRP_MAPPING CurMapping;
PLIST_ENTRY CurEntry;
- ULONG Index;
- ULONG Value;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
*Flags = 0;
ASSERT(Tag != NULL);
- KeAcquireSpinLockAtDpcLevel(&This->Lock);
- CurEntry = This->ListHead.Flink;
- if (CurEntry == &This->ListHead)
+ CurEntry = ExInterlockedRemoveHeadList(&This->ListHead, &This->Lock);
+ if (!CurEntry)
{
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
This->OutOfMapping = TRUE;
This->StartStream = FALSE;
return STATUS_UNSUCCESSFUL;
}
- while (CurEntry != &This->ListHead)
+ CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
+
+ *PhysicalAddress = MmGetPhysicalAddress(CurMapping->Buffer);
+ *VirtualAddress = CurMapping->Buffer;
+ *ByteCount = CurMapping->BufferSize;
+
+ InterlockedDecrement(&This->NumMappings);
+ This->NumDataAvailable -= CurMapping->BufferSize;
+
+ if (CurMapping->OriginalBuffer)
{
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
- for(Index = 0; Index < CurMapping->NumTags; Index++)
- {
- Value = CurMapping->References & ( 1 << Index);
- if (CurMapping->Tag[Index] == NULL && Value)
- {
- /* found a free mapping within audio irp */
- GetMapping(This, Index, Tag, CurMapping, PhysicalAddress, VirtualAddress, ByteCount, Flags);
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
- return STATUS_SUCCESS;
- }
- }
- CurEntry = CurEntry->Flink;
+ /* last partial buffer */
+ *Flags = 1;
+
+ /* store tag */
+ CurMapping->Tag = Tag;
+
+ /* insert into list to free later */
+ ExInterlockedInsertTailList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
}
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
- This->OutOfMapping = TRUE;
- This->StartStream = FALSE;
- DPRINT("No Mapping available\n");
- return STATUS_UNSUCCESSFUL;
+ else
+ {
+ /* we can free this entry now */
+ FreeItem(CurMapping, TAG_PORTCLASS);
+ }
+ DPRINT("IIrpQueue_fnGetMappingWithTag Tag %p\n", Tag);
+ return STATUS_SUCCESS;
}
NTSTATUS
{
PIRP_MAPPING CurMapping = NULL;
PLIST_ENTRY CurEntry;
- ULONG Index = 0;
- ULONG Found;
IIrpQueueImpl * This = (IIrpQueueImpl*)iface;
- KeAcquireSpinLockAtDpcLevel(&This->Lock);
-
- CurEntry = This->ListHead.Flink;
- if (CurEntry == &This->ListHead)
- {
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
- return STATUS_UNSUCCESSFUL;
- }
+ DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p\n", Tag);
- Found = FALSE;
- while (CurEntry != &This->ListHead)
+ CurEntry = ExInterlockedRemoveHeadList(&This->FreeHead, &This->Lock);
+ if (!CurMapping)
{
- CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
- for(Index = 0; Index < CurMapping->NumTags; Index++)
- {
- if (CurMapping->Tag[Index] == Tag)
- {
- Found = TRUE;
- CurMapping->Tag[Index] = NULL;
- break;
- }
- }
- if (Found)
- break;
-
- CurEntry = CurEntry->Flink;
- }
-
- if (!Found)
- {
- DPRINT1("Tag %p not found\n", Tag);
- ASSERT(Found);
+ return STATUS_SUCCESS;
}
- DPRINT("References %x\n", CurMapping->References);
- CurMapping->References &= ~(1 << Index);
- if (CurMapping->References)
+ CurMapping = CONTAINING_RECORD(CurEntry, IRP_MAPPING, Entry);
+ if (CurMapping->Tag != Tag)
{
- /* released mapping is not the last mapping of the irp */
- DPRINT1("IIrpQueue_fnReleaseMappingWithTag Tag %p Index %u NumTags %u Refs %x\n", Tag, Index, CurMapping->NumTags, CurMapping->References);
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
+ /* the released mapping is not the last one */
+ ExInterlockedInsertHeadList(&This->FreeHead, &CurMapping->Entry, &This->Lock);
return STATUS_SUCCESS;
}
- RemoveEntryList(&CurMapping->Entry);
-
/* last mapping of the irp, free irp */
- DPRINT("Freeing mapping %p\n", CurMapping);
- InterlockedDecrement(&This->NumMappings);
- FreeMappingRoutine(CurMapping);
- KeReleaseSpinLockFromDpcLevel(&This->Lock);
+ DPRINT("IIrpQueue_fnReleaseMappingWithTag Tag %p Mapping %p FREED\n", Tag, CurMapping);
+ FreeMappingRoutine(CurMapping);
return STATUS_SUCCESS;
}
return This->OutOfMapping;
}
+VOID
+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");
+}
+
+
static IIrpQueueVtbl vt_IIrpQueue =
{
IIrpQueue_fnQueryInterface,
IIrpQueue_fnUpdateFormat,
IIrpQueue_fnGetMappingWithTag,
IIrpQueue_fnReleaseMappingWithTag,
- IIrpQueue_fnHasLastMappingFailed
+ IIrpQueue_fnHasLastMappingFailed,
+ IIrpQueue_fnPrintQueueStatus
};