407 lines
6.9 KiB
C
407 lines
6.9 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sync.c
|
|
|
|
Abstract:
|
|
|
|
This file contains code for the video port synchronization routines.
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
--*/
|
|
|
|
#include "videoprt.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, VideoPortCreateEvent)
|
|
#pragma alloc_text(PAGE, VideoPortCreateSpinLock)
|
|
#endif
|
|
|
|
VP_STATUS
|
|
VideoPortCreateSpinLock(
|
|
IN PVOID HwDeviceExtension,
|
|
OUT PSPIN_LOCK *SpinLock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a spin lock object
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - pointer to the miniports device extension
|
|
|
|
SpinLock - Location in which to store the pointer to the newly
|
|
acquired spin lock.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR if the spin lock was created successfully, otherwise
|
|
an appropriate error message is returned.
|
|
|
|
Notes:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
ASSERT(HwDeviceExtension != NULL);
|
|
|
|
*SpinLock = ExAllocatePoolWithTag(NonPagedPool,
|
|
sizeof(VIDEO_PORT_SPIN_LOCK),
|
|
VP_TAG);
|
|
|
|
if (*SpinLock) {
|
|
KeInitializeSpinLock(&(*SpinLock)->Lock);
|
|
return NO_ERROR;
|
|
} else {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
VP_STATUS
|
|
VideoPortDeleteSpinLock(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PSPIN_LOCK SpinLock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes the given spin lock
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - pointer to the miniports device extension
|
|
|
|
SpinLock - A pointer to the spin lock being deleted.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR if the spin lock is deleted successfully.
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(HwDeviceExtension != NULL);
|
|
ASSERT(SpinLock != NULL);
|
|
|
|
ExFreePool(SpinLock);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
VideoPortAcquireSpinLock(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PSPIN_LOCK SpinLock,
|
|
OUT PUCHAR OldIrql
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Acquires the given spin lock
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - pointer to the miniports device extension
|
|
|
|
SpinLock - The spin lock being acquired
|
|
|
|
OldIrql - location in which to store the old IRQL level
|
|
|
|
Returns:
|
|
|
|
none
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(HwDeviceExtension != NULL);
|
|
ASSERT(SpinLock != NULL);
|
|
|
|
KeAcquireSpinLock(&SpinLock->Lock, OldIrql);
|
|
}
|
|
|
|
VOID
|
|
VideoPortAcquireSpinLockAtDpcLevel(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PSPIN_LOCK SpinLock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Acquires the given spin lock.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - pointer to the miniports device extension
|
|
|
|
SpinLock - The spin lock being acquired
|
|
|
|
Returns:
|
|
|
|
none
|
|
|
|
Notes:
|
|
|
|
This routine can only be called inside a DPC.
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
ASSERT(HwDeviceExtension != NULL);
|
|
ASSERT(SpinLock != NULL);
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&SpinLock->Lock);
|
|
}
|
|
|
|
VOID
|
|
VideoPortReleaseSpinLock(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PSPIN_LOCK SpinLock,
|
|
IN UCHAR NewIrql
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Releases ownership of a given spin lock
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - pointer to the miniports device extension
|
|
|
|
SpinLock - the spin lock being released
|
|
|
|
NewIrql - Irql level to restore to.
|
|
|
|
Returns:
|
|
|
|
none
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(HwDeviceExtension != NULL);
|
|
ASSERT(SpinLock != NULL);
|
|
|
|
KeReleaseSpinLock(&SpinLock->Lock, NewIrql);
|
|
}
|
|
|
|
VOID
|
|
VideoPortReleaseSpinLockFromDpcLevel(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PSPIN_LOCK SpinLock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Releases ownership of a given spin lock
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - pointer to the miniports device extension
|
|
|
|
SpinLock - the spin lock being released
|
|
|
|
Returns:
|
|
|
|
none
|
|
|
|
Notes:
|
|
|
|
This routine can only be called inside a DPC.
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
ASSERT(HwDeviceExtension != NULL);
|
|
ASSERT(SpinLock != NULL);
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&SpinLock->Lock);
|
|
}
|
|
|
|
VP_STATUS
|
|
VideoPortCreateEvent(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG EventFlag,
|
|
PVOID Unused,
|
|
OUT PEVENT *ppEvent
|
|
)
|
|
{
|
|
ULONG size;
|
|
PEVENT p;
|
|
EVENT_TYPE EventType;
|
|
|
|
|
|
size = sizeof(VIDEO_PORT_EVENT);
|
|
|
|
//
|
|
// Align size to next higher multiple of 8.
|
|
//
|
|
|
|
size = (size + 7) & ~7;
|
|
|
|
p = (PEVENT) ExAllocatePoolWithTag( NonPagedPool,
|
|
size + sizeof(KEVENT),
|
|
VP_TAG );
|
|
if ( p ) {
|
|
|
|
p->fFlags = 0;
|
|
p->pKEvent = (PUCHAR) p + size;
|
|
|
|
if( (EventFlag & EVENT_TYPE_MASK) == NOTIFICATION_EVENT ) {
|
|
|
|
EventType = NotificationEvent;
|
|
|
|
} else {
|
|
|
|
EventType = SynchronizationEvent;
|
|
}
|
|
|
|
KeInitializeEvent( p->pKEvent,
|
|
EventType,
|
|
(BOOLEAN) (EventFlag & INITIAL_EVENT_STATE_MASK ) );
|
|
|
|
*ppEvent = p;
|
|
|
|
return NO_ERROR;
|
|
|
|
} else {
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
VP_STATUS
|
|
VideoPortDeleteEvent(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PEVENT pEvent
|
|
)
|
|
{
|
|
if ( pEvent == NULL ) {
|
|
|
|
pVideoDebugPrint((Error, "VideoPortDeleteEvent: Can't delete NULL event\n"));
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ( pEvent->fFlags & ENG_EVENT_FLAG_IS_MAPPED_USER ) {
|
|
|
|
pVideoDebugPrint((Error, "VideoPortDeleteEvent: Can't delete mapped user event\n"));
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( pEvent->pKEvent == NULL ) {
|
|
|
|
pVideoDebugPrint((Error, "VideoPortDeleteEvent: pKEvent is NULL\n"));
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
ExFreePool( (PVOID) pEvent );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
LONG
|
|
VideoPortSetEvent(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PEVENT pEvent
|
|
)
|
|
{
|
|
return( KeSetEvent(pEvent->pKEvent, 0, FALSE) );
|
|
}
|
|
|
|
VOID
|
|
VideoPortClearEvent(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PEVENT pEvent
|
|
)
|
|
{
|
|
KeClearEvent(pEvent->pKEvent);
|
|
}
|
|
|
|
LONG
|
|
VideoPortReadStateEvent(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PEVENT pEvent
|
|
)
|
|
{
|
|
return ( KeReadStateEvent(pEvent->pKEvent) );
|
|
}
|
|
|
|
|
|
VP_STATUS
|
|
VideoPortWaitForSingleObject(
|
|
IN PVOID HwDeviceExtension,
|
|
IN PVOID pEvent,
|
|
IN PLARGE_INTEGER Timeout
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if ( pEvent == NULL ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( ((PEVENT) pEvent)->pKEvent == NULL) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (( (PEVENT) pEvent)->fFlags & ENG_EVENT_FLAG_IS_MAPPED_USER ) {
|
|
|
|
pVideoDebugPrint((Error, "VideoPortVideoPortWaitForSingleObject: No wait ing on mapped user event\n")) ;
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
status = KeWaitForSingleObject( ((PEVENT) pEvent)->pKEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
Timeout );
|
|
|
|
if (status == STATUS_TIMEOUT) {
|
|
|
|
return WAIT_TIMEOUT;
|
|
|
|
} else if (NT_SUCCESS(status)) {
|
|
|
|
return NO_ERROR;
|
|
|
|
} else {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|