diff options
Diffstat (limited to 'AVStream/avshws/hwsim.cpp')
| -rw-r--r-- | AVStream/avshws/hwsim.cpp | 868 |
1 files changed, 0 insertions, 868 deletions
diff --git a/AVStream/avshws/hwsim.cpp b/AVStream/avshws/hwsim.cpp deleted file mode 100644 index 9a6d5f86..00000000 --- a/AVStream/avshws/hwsim.cpp +++ /dev/null @@ -1,868 +0,0 @@ -/************************************************************************** - - AVStream Simulated Hardware Sample - - Copyright (c) 2001, Microsoft Corporation. - - File: - - hwsim.cpp - - Abstract: - - This file contains the hardware simulation. It fakes "DMA" transfers, - scatter gather mapping handling, ISR's, etc... The ISR routine in - here will be called when an ISR would be generated by the fake hardware - and it will directly call into the device level ISR for more accurate - simulation. - - History: - - created 3/9/2001 - -**************************************************************************/ - -#include "avshws.h" - - -/*************************************************/ -KDEFERRED_ROUTINE SimulatedInterrupt; - -void -SimulatedInterrupt ( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArg1, - IN PVOID SystemArg2 - ) -{ - CHardwareSimulation* HardwareSim = (CHardwareSimulation*)DeferredContext; - - if (HardwareSim) - { - HardwareSim -> FakeHardware (); - } -} - - -/************************************************************************** - - PAGEABLE CODE - -**************************************************************************/ - -#ifdef ALLOC_PRAGMA -#pragma code_seg("PAGE") -#endif // ALLOC_PRAGMA - - - -CHardwareSimulation:: -CHardwareSimulation ( - IN IHardwareSink *HardwareSink - ) : - m_HardwareSink (HardwareSink), - m_ScatterGatherMappingsMax (SCATTER_GATHER_MAPPINGS_MAX) - -/*++ - -Routine Description: - - Construct a hardware simulation - -Arguments: - - HardwareSink - - The hardware sink interface. This is used to trigger - fake interrupt service routines from. - -Return Value: - - Success / Failure - ---*/ - -{ - - PAGED_CODE(); - - // - // Initialize the DPC's, timer's, and locks necessary to simulate - // this capture hardware. - // - KeInitializeDpc ( - &m_IsrFakeDpc, - SimulatedInterrupt, - this - ); - - KeInitializeEvent ( - &m_HardwareEvent, - SynchronizationEvent, - FALSE - ); - - KeInitializeTimer (&m_IsrTimer); - - KeInitializeSpinLock (&m_ListLock); - -} - -/*************************************************/ - - -CHardwareSimulation * -CHardwareSimulation:: -Initialize ( - IN KSOBJECT_BAG Bag, - IN IHardwareSink *HardwareSink - ) - -/*++ - -Routine Description: - - Initialize the hardware simulation - -Arguments: - - HardwareSink - - The hardware sink interface. This is what ISR's will be - triggered through. - -Return Value: - - A fully initialized hardware simulation or NULL if the simulation - could not be initialized. - ---*/ - -{ - - PAGED_CODE(); - - CHardwareSimulation *HwSim = - new (NonPagedPoolNx, 'miSH') CHardwareSimulation (HardwareSink); - - return HwSim; - -} - -/*************************************************/ - - -NTSTATUS -CHardwareSimulation:: -Start ( - IN CImageSynthesizer *ImageSynth, - IN LONGLONG TimePerFrame, - IN ULONG Width, - IN ULONG Height, - IN ULONG ImageSize - ) - -/*++ - -Routine Description: - - Start the hardware simulation. This will kick the interrupts on, - begin issuing DPC's, filling in capture information, etc... - We keep track of starvation starting at this point. - -Arguments: - - ImageSynth - - The image synthesizer to use to generate pictures to display - on the capture buffer. - - TimePerFrame - - The time per frame... we issue interrupts this often. - - Width - - The image width - - Height - - The image height - - ImageSize - - The size of the image. We allocate a temporary scratch buffer - based on this size to fake hardware. - -Return Value: - - Success / Failure (typical failure will be out of memory on the - scratch buffer, etc...) - ---*/ - -{ - - PAGED_CODE(); - - NTSTATUS Status = STATUS_SUCCESS; - - m_ImageSynth = ImageSynth; - m_TimePerFrame = TimePerFrame; - m_ImageSize = ImageSize; - m_Height = Height; - m_Width = Width; - - InitializeListHead (&m_ScatterGatherMappings); - m_NumMappingsCompleted = 0; - m_ScatterGatherMappingsQueued = 0; - m_NumFramesSkipped = 0; - m_InterruptTime = 0; - - KeQuerySystemTime (&m_StartTime); - - // - // Allocate a scratch buffer for the synthesizer. - // - m_SynthesisBuffer = reinterpret_cast <PUCHAR> ( - ExAllocatePoolWithTag ( - NonPagedPoolNx, - m_ImageSize, - AVSHWS_POOLTAG - ) - ); - - if (!m_SynthesisBuffer) { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - - // - // If everything is ok, start issuing interrupts. - // - if (NT_SUCCESS (Status)) { - - // - // Initialize the entry lookaside. - // - ExInitializeNPagedLookasideList ( - &m_ScatterGatherLookaside, - NULL, - NULL, - POOL_NX_ALLOCATION, - sizeof (SCATTER_GATHER_ENTRY), - 'nEGS', - 0 - ); - - // - // Set up the synthesizer with the width, height, and scratch buffer. - // - m_ImageSynth -> SetImageSize (m_Width, m_Height); - m_ImageSynth -> SetBuffer (m_SynthesisBuffer); - - LARGE_INTEGER NextTime; - NextTime.QuadPart = m_StartTime.QuadPart + m_TimePerFrame; - - m_HardwareState = HardwareRunning; - KeSetTimer (&m_IsrTimer, NextTime, &m_IsrFakeDpc); - - } - - return Status; - -} - -/*************************************************/ - - -NTSTATUS -CHardwareSimulation:: -Pause ( - BOOLEAN Pausing - ) - -/*++ - -Routine Description: - - Pause the hardware simulation... When the hardware simulation is told - to pause, it stops issuing interrupts, etc... but it does not reset - the counters - -Arguments: - - Pausing - - Indicates whether the hardware is pausing or not. - - TRUE - - Pause the hardware - - FALSE - - Unpause the hardware from a previous pause - - -Return Value: - - Success / Failure - ---*/ - -{ - - PAGED_CODE(); - - if (Pausing && m_HardwareState == HardwareRunning) { - // - // If we were running, stop completing mappings, etc... - // - m_StopHardware = TRUE; - - KeWaitForSingleObject ( - &m_HardwareEvent, - Suspended, - KernelMode, - FALSE, - NULL - ); - - NT_ASSERT (m_StopHardware == FALSE); - - m_HardwareState = HardwarePaused; - - } else if (!Pausing && m_HardwareState == HardwarePaused) { - - // - // For unpausing the hardware, we need to compute the relative time - // and restart interrupts. - // - LARGE_INTEGER UnpauseTime; - - KeQuerySystemTime (&UnpauseTime); - m_InterruptTime = (ULONG) ( - (UnpauseTime.QuadPart - m_StartTime.QuadPart) / - m_TimePerFrame - ); - - UnpauseTime.QuadPart = m_StartTime.QuadPart + - (m_InterruptTime + 1) * m_TimePerFrame; - - m_HardwareState = HardwareRunning; - KeSetTimer (&m_IsrTimer, UnpauseTime, &m_IsrFakeDpc); - - } - - return STATUS_SUCCESS; - -} - -/************************************************************************** - - LOCKED CODE - -**************************************************************************/ - -#ifdef ALLOC_PRAGMA -#pragma code_seg() -#endif // ALLOC_PRAGMA - -NTSTATUS -CHardwareSimulation:: -Stop ( - ) - -/*++ - -Routine Description: - - Stop the hardware simulation.... Wait until the hardware simulation - has successfully stopped and then return. - -Arguments: - - None - -Return Value: - - Success / Failure - ---*/ - -{ - KIRQL Irql; - // - // If the hardware is told to stop while it's running, we need to - // halt the interrupts first. If we're already paused, this has - // already been done. - // - if (m_HardwareState == HardwareRunning) { - - m_StopHardware = TRUE; - - KeWaitForSingleObject ( - &m_HardwareEvent, - Suspended, - KernelMode, - FALSE, - NULL - ); - - NT_ASSERT (m_StopHardware == FALSE); - - } - - m_HardwareState = HardwareStopped; - - // - // The image synthesizer may still be around. Just for safety's - // sake, NULL out the image synthesis buffer and toast it. - // - m_ImageSynth -> SetBuffer (NULL); - - if (m_SynthesisBuffer) { - ExFreePool (m_SynthesisBuffer); - m_SynthesisBuffer = NULL; - } - - // - // Protect the S/G list - // - KeAcquireSpinLock (&m_ListLock, &Irql); - // - // Free S/G buffer - // - // - while (m_ScatterGatherMappingsQueued > 0) { - LIST_ENTRY *listEntry = RemoveHeadList (&m_ScatterGatherMappings); - m_ScatterGatherMappingsQueued--; - PSCATTER_GATHER_ENTRY SGEntry = - reinterpret_cast <PSCATTER_GATHER_ENTRY> ( - CONTAINING_RECORD ( - listEntry, - SCATTER_GATHER_ENTRY, - ListEntry - ) - ); - // - // Release the scatter / gather entry back to our lookaside. - // - ExFreeToNPagedLookasideList ( - &m_ScatterGatherLookaside, - reinterpret_cast <PVOID> (SGEntry) - ); - } - - m_NumMappingsCompleted = 0; - m_ScatterGatherBytesQueued = 0; - // - // Delete the scatter / gather lookaside for this run. - // - ExDeleteNPagedLookasideList (&m_ScatterGatherLookaside); - - KeReleaseSpinLock (&m_ListLock, Irql); - - return STATUS_SUCCESS; - -} - - -ULONG -CHardwareSimulation:: -ReadNumberOfMappingsCompleted ( - ) - -/*++ - -Routine Description: - - Read the number of scatter / gather mappings which have been - completed (TOTAL NUMBER) since the last reset of the simulated - hardware - -Arguments: - - None - -Return Value: - - Total number of completed mappings. - ---*/ - -{ - - // - // Don't care if this is being updated this moment in the DPC... I only - // need a number to return which isn't too great (too small is ok). - // In real hardware, this wouldn't be done this way anyway. - // - return m_NumMappingsCompleted; - -} - -/*************************************************/ - - -ULONG -CHardwareSimulation:: -ProgramScatterGatherMappings ( - IN PKSSTREAM_POINTER Clone, - IN PUCHAR *Buffer, - IN PKSMAPPING Mappings, - IN ULONG MappingsCount, - IN ULONG MappingStride - ) - -/*++ - -Routine Description: - - Program the scatter gather mapping list. This shoves a bunch of - entries on a list for access during the fake interrupt. Note that - we have physical addresses here only for simulation. We really - access via the virtual address.... although we chunk it into multiple - buffers to more realistically simulate S/G - -Arguments: - - Buffer - - The virtual address of the buffer mapped by the mapping list - - Mappings - - The KSMAPPINGS array corresponding to the buffer - - MappingsCount - - The number of mappings in the mappings array - - MappingStride - - The mapping stride used in initialization of AVStream DMA - -Return Value: - - Number of mappings actually inserted. - ---*/ - -{ - - KIRQL Irql; - - ULONG MappingsInserted = 0; - - // - // Protect our S/G list with a spinlock. - // - KeAcquireSpinLock (&m_ListLock, &Irql); - - // - // Loop through the scatter / gather list and break the buffer up into - // chunks equal to the scatter / gather mappings. Stuff the virtual - // addresses of these chunks on a list somewhere. We update the buffer - // pointer the caller passes as a more convenient way of doing this. - // - // If I could just remap physical in the list to virtual easily here, - // I wouldn't need to do it. - // -#if !defined(_X86_) - do - { - PSCATTER_GATHER_ENTRY Entry = - reinterpret_cast <PSCATTER_GATHER_ENTRY> ( - ExAllocateFromNPagedLookasideList ( - &m_ScatterGatherLookaside - ) - ); - - if (!Entry) { - break; - } - Entry -> Virtual = *Buffer; - Entry -> ByteCount = MappingsCount; - Entry -> CloneEntry = Clone; - - // - // Move forward a specific number of bytes in chunking this into - // mapping sized va buffers. - // - *Buffer += MappingsCount; - Mappings = reinterpret_cast <PKSMAPPING> ( - (reinterpret_cast <PUCHAR> (Mappings) + MappingStride) - ); - - InsertTailList (&m_ScatterGatherMappings, &(Entry -> ListEntry)); - MappingsInserted = MappingsCount; - m_ScatterGatherMappingsQueued++; - m_ScatterGatherBytesQueued += MappingsCount; - - } - while(FALSE); - -#else - for (ULONG MappingNum = 0; - MappingNum < MappingsCount && - m_ScatterGatherMappingsQueued < m_ScatterGatherMappingsMax; - MappingNum++) { - - PSCATTER_GATHER_ENTRY Entry = - reinterpret_cast <PSCATTER_GATHER_ENTRY> ( - ExAllocateFromNPagedLookasideList ( - &m_ScatterGatherLookaside - ) - ); - - if (!Entry) { - break; - } - - Entry -> Virtual = *Buffer; - Entry -> ByteCount = Mappings -> ByteCount; - - // - // Move forward a specific number of bytes in chunking this into - // mapping sized va buffers. - // - *Buffer += Entry -> ByteCount; - Mappings = reinterpret_cast <PKSMAPPING> ( - (reinterpret_cast <PUCHAR> (Mappings) + MappingStride) - ); - - InsertTailList (&m_ScatterGatherMappings, &(Entry -> ListEntry)); - MappingsInserted++; - m_ScatterGatherMappingsQueued++; - m_ScatterGatherBytesQueued += Entry -> ByteCount; - - } -#endif - - KeReleaseSpinLock (&m_ListLock, Irql); - - return MappingsInserted; - -} - -/*************************************************/ - - -NTSTATUS -CHardwareSimulation:: -FillScatterGatherBuffers ( - ) - -/*++ - -Routine Description: - - The hardware has synthesized a buffer in scratch space and we're to - fill scatter / gather buffers. - -Arguments: - - None - -Return Value: - - Success / Failure - ---*/ - -{ - - // - // We're using this list lock to protect our scatter / gather lists instead - // of some hardware mechanism / KeSynchronizeExecution / whatever. - // - KeAcquireSpinLockAtDpcLevel (&m_ListLock); - - PUCHAR Buffer = reinterpret_cast <PUCHAR> (m_SynthesisBuffer); - ULONG BufferRemaining = m_ImageSize; - - // - // For simplification, if there aren't enough scatter / gather buffers - // queued, we don't partially fill the ones that are available. We just - // skip the frame and consider it starvation. - // - // This could be enforced by only programming scatter / gather mappings - // for a buffer if all of them fit in the table also... - // - while (BufferRemaining && - m_ScatterGatherMappingsQueued > 0 && - m_ScatterGatherBytesQueued >= BufferRemaining) { - - LIST_ENTRY *listEntry = RemoveHeadList (&m_ScatterGatherMappings); - m_ScatterGatherMappingsQueued--; - - PSCATTER_GATHER_ENTRY SGEntry = - reinterpret_cast <PSCATTER_GATHER_ENTRY> ( - CONTAINING_RECORD ( - listEntry, - SCATTER_GATHER_ENTRY, - ListEntry - ) - ); - - // - // Since we're software, we'll be accessing this by virtual address... - // - ULONG BytesToCopy = - (BufferRemaining < SGEntry -> ByteCount) ? - BufferRemaining : - SGEntry -> ByteCount; - - LONG Width = m_Width*(m_ImageSynth->GetBytesPerPixel()); - - LONG Stride = Width; - if(SGEntry->CloneEntry->StreamHeader->Size >= sizeof(KSSTREAM_HEADER)+sizeof(KS_FRAME_INFO)) - { - PKS_FRAME_INFO FrameInfo = reinterpret_cast <PKS_FRAME_INFO> (SGEntry->CloneEntry->StreamHeader+1); - if(FrameInfo->lSurfacePitch != 0) - { - Stride = FrameInfo->lSurfacePitch; - if(FrameInfo->lSurfacePitch < 0) - { - Stride = -Stride; - } - } - } - - for(ULONG y = 0; y < m_Height; y++) - { - RtlCopyMemory((SGEntry->Virtual+(ULONG)Stride*y), Buffer, Width); - Buffer += Width; - BytesToCopy -= Width; - BufferRemaining -= Width; - } - - m_NumMappingsCompleted++; - m_ScatterGatherBytesQueued -= SGEntry -> ByteCount; - - // - // Release the scatter / gather entry back to our lookaside. - // - ExFreeToNPagedLookasideList ( - &m_ScatterGatherLookaside, - reinterpret_cast <PVOID> (SGEntry) - ); - - } - - KeReleaseSpinLockFromDpcLevel (&m_ListLock); - - if (BufferRemaining) return STATUS_INSUFFICIENT_RESOURCES; - else return STATUS_SUCCESS; - -} - -/*************************************************/ - - -void -CHardwareSimulation:: -FakeHardware ( - ) - -/*++ - -Routine Description: - - Simulate an interrupt and what the hardware would have done in the - time since the previous interrupt. - -Arguments: - - None - -Return Value: - - None - ---*/ - -{ - - m_InterruptTime++; - - // - // The hardware can be in a pause state in which case, it issues interrupts - // but does not complete mappings. In this case, don't bother synthesizing - // a frame and doing the work of looking through the mappings table. - // - if (m_HardwareState == HardwareRunning) { - - // - // Generate a "time stamp" just to overlay it onto the capture image. - // It makes it more exciting than bars that do nothing. - // - LONGLONG PtsRel = ((m_InterruptTime + 1) * m_TimePerFrame); - - ULONG Min = (ULONG)(PtsRel / 600000000); - ULONG RemMin = (ULONG)(PtsRel % 600000000); - ULONG Sec = (ULONG)(RemMin / 10000000); - ULONG RemSec = (ULONG)(RemMin % 10000000); - ULONG Hund = (ULONG)(RemSec / 100000); - - // - // Synthesize a buffer in scratch space. - // - m_ImageSynth -> SynthesizeBars (); - - CHAR Text [256]; - Text[0] = '\0'; - (void) RtlStringCbPrintfA(Text, sizeof(Text), "%ld:%02ld.%02ld", Min, Sec, Hund); - - // - // Overlay a clock onto the scratch space image. - // - m_ImageSynth -> OverlayText ( - POSITION_CENTER, - (m_Height - 28), - 1, - Text, - BLACK, - WHITE - ); - - // - // Overlay a counter of skipped frames onto the scratch image. - // - (void) RtlStringCbPrintfA(Text, sizeof(Text), "Skipped: %ld", m_NumFramesSkipped); - m_ImageSynth -> OverlayText ( - 10, - 10, - 1, - Text, - TRANSPARENT, - BLUE - ); - - // - // Fill scatter gather buffers - // - if (!NT_SUCCESS (FillScatterGatherBuffers ())) { - InterlockedIncrement (PLONG (&m_NumFramesSkipped)); - } - - } - - // - // Issue an interrupt to our hardware sink. This is a "fake" interrupt. - // It will occur at DISPATCH_LEVEL. - // - m_HardwareSink -> Interrupt (); - - // - // Reschedule the timer if the hardware isn't being stopped. - // - if (!m_StopHardware) { - - // - // Reschedule the timer for the next interrupt time. - // - LARGE_INTEGER NextTime; - NextTime.QuadPart = m_StartTime.QuadPart + - (m_TimePerFrame * (m_InterruptTime + 1)); - - KeSetTimer (&m_IsrTimer, NextTime, &m_IsrFakeDpc); - - } else { - // - // If someone is waiting on the hardware to stop, raise the stop - // event and clear the flag. - // - m_StopHardware = FALSE; - KeSetEvent (&m_HardwareEvent, IO_NO_INCREMENT, FALSE); - } - -} |
