Author: janderwald Date: Mon Dec 8 13:08:07 2008 New Revision: 37943
URL: http://svn.reactos.org/svn/reactos?rev=37943&view=rev Log: - Experimental IInterrupt object implementation
Added: trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.c (with props) Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/portcls.rbuild trunk/reactos/drivers/wdm/audio/backpln/portcls/stubs.c
Added: trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.c (added) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.c [iso-8859-1] Mon Dec 8 13:08:07 2008 @@ -1,0 +1,336 @@ +#include "private.h" + +typedef struct +{ + LIST_ENTRY ListEntry; + PINTERRUPTSYNCROUTINE SyncRoutine; + PVOID DynamicContext; +}SYNC_ENTRY, *PSYNC_ENTRY; + +typedef struct +{ + IInterruptSyncVtbl *lpVtbl; + + LONG ref; + KSPIN_LOCK Lock; + LIST_ENTRY ServiceRoutines; + PKINTERRUPT Interrupt; + INTERRUPTSYNCMODE Mode; + PRESOURCELIST ResourceList; + ULONG ResourceIndex; + + PINTERRUPTSYNCROUTINE SyncRoutine; + PVOID DynamicContext; +}IInterruptSyncImpl; + + +//--------------------------------------------------------------- +// IUnknown methods +// + +const GUID IID_IInterruptSync; + +NTSTATUS +NTAPI +IInterruptSync_fnQueryInterface( + IInterruptSync * iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + if (IsEqualGUIDAligned(refiid, &IID_IInterruptSync)) + { + *Output = &This->lpVtbl; + _InterlockedIncrement(&This->ref); + return STATUS_SUCCESS; + } + + return STATUS_UNSUCCESSFUL; +} + +ULONG +NTAPI +IInterruptSync_fnAddRef( + IInterruptSync * iface) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + DPRINT("IInterruptSync_AddRef: This %p\n", This); + + return _InterlockedIncrement(&This->ref); +} + +ULONG +NTAPI +IInterruptSync_fnRelease( + IInterruptSync* iface) +{ + PLIST_ENTRY CurEntry; + PSYNC_ENTRY Entry; + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + _InterlockedDecrement(&This->ref); + + DPRINT("IInterruptSync_Release: This %p new ref %u\n", This, This->ref); + + if (This->ref == 0) + { + if (This->Interrupt) + { + DPRINT1("Interrupt not disconnected! %p\n", This->Interrupt); + IoDisconnectInterrupt(This->Interrupt); + } + while(!IsListEmpty(&This->ServiceRoutines)) + { + CurEntry = RemoveHeadList(&This->ServiceRoutines); + Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry); + ExFreePoolWithTag(Entry, TAG_PORTCLASS); + } + + This->ResourceList->lpVtbl->Release(This->ResourceList); + ExFreePoolWithTag(This, TAG_PORTCLASS); + return 0; + } + /* Return new reference count */ + return This->ref; +} + +//--------------------------------------------------------------- +// IInterruptSync methods +// + + +BOOLEAN +NTAPI +IInterruptSynchronizedRoutine( + IN PVOID ServiceContext) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)ServiceContext; + + return This->SyncRoutine((IInterruptSync*)This, This->DynamicContext); +} + +NTSTATUS +NTAPI +IInterruptSync_fnCallSynchronizedRoutine( + IN IInterruptSync * iface, + IN PINTERRUPTSYNCROUTINE Routine, + IN PVOID DynamicContext) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + if (!This->Interrupt) + { + DPRINT("IInterruptSync_CallSynchronizedRoutine %p no interrupt connected\n", This); + return STATUS_UNSUCCESSFUL; + } + + This->SyncRoutine = Routine; + This->DynamicContext = DynamicContext; + + return KeSynchronizeExecution(This->Interrupt, IInterruptSynchronizedRoutine, (PVOID)This); +} + +NTAPI +PKINTERRUPT +IInterruptSync_fnGetKInterrupt( + IN IInterruptSync * iface) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + return This->Interrupt; +} + +BOOLEAN +NTAPI +IInterruptServiceRoutine( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext) +{ + PLIST_ENTRY CurEntry; + PSYNC_ENTRY Entry; + NTSTATUS Status; + BOOL Success; + IInterruptSyncImpl * This = (IInterruptSyncImpl*)ServiceContext; + + if (This->Mode == InterruptSyncModeNormal) + { + CurEntry = This->ServiceRoutines.Flink; + while (CurEntry != &This->ServiceRoutines) + { + Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry); + Status = Entry->SyncRoutine((IInterruptSync*)This, Entry->DynamicContext); + if (NT_SUCCESS(Status)) + { + return TRUE; + } + CurEntry = CurEntry->Flink; + } + return FALSE; + } + else if (This->Mode == InterruptSyncModeAll) + { + CurEntry = This->ServiceRoutines.Flink; + while (CurEntry != &This->ServiceRoutines) + { + Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry); + Status = Entry->SyncRoutine((IInterruptSync*)This, Entry->DynamicContext); + CurEntry = CurEntry->Flink; + } + DPRINT("Returning TRUE with mode InterruptSyncModeAll\n"); + return TRUE; //FIXME + } + else if (This->Mode == InterruptSyncModeRepeat) + { + do + { + Success = FALSE; + CurEntry = This->ServiceRoutines.Flink; + while (CurEntry != &This->ServiceRoutines) + { + Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry); + Status = Entry->SyncRoutine((IInterruptSync*)This, Entry->DynamicContext); + if (NT_SUCCESS(Status)) + Success = TRUE; + CurEntry = CurEntry->Flink; + } + }while(Success); + DPRINT("Returning TRUE with mode InterruptSyncModeRepeat\n"); + return TRUE; //FIXME + } + else + { + DPRINT("Unknown mode %u\n", This->Mode); + return FALSE; //FIXME + } +} + + +NTSTATUS +NTAPI +IInterruptSync_fnConnect( + IN IInterruptSync * iface) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + NTSTATUS Status; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + + Descriptor = This->ResourceList->lpVtbl->FindTranslatedEntry(This->ResourceList, CmResourceTypeInterrupt, This->ResourceIndex); + if (!Descriptor) + return STATUS_UNSUCCESSFUL; + + if (IsListEmpty(&This->ServiceRoutines)) + return STATUS_UNSUCCESSFUL; + + Status = IoConnectInterrupt(&This->Interrupt, + IInterruptServiceRoutine, + (PVOID)This, + &This->Lock, Descriptor->u.Interrupt.Vector, + Descriptor->u.Interrupt.Level, + Descriptor->u.Interrupt.Level, //FIXME + LevelSensitive, //FIXME + TRUE, //FIXME + Descriptor->u.Interrupt.Affinity, + FALSE); + + return Status; +} + + +VOID +NTAPI +IInterruptSync_fnDisconnect( + IN IInterruptSync * iface) +{ + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + if (!This->Interrupt) + { + DPRINT("IInterruptSync_Disconnect %p no interrupt connected\n", This); + return; + } + + IoDisconnectInterrupt(This->Interrupt); + This->Interrupt = NULL; +} + +NTSTATUS +NTAPI +IInterruptSync_fnRegisterServiceRoutine( + IN IInterruptSync * iface, + IN PINTERRUPTSYNCROUTINE Routine, + IN PVOID DynamicContext, + IN BOOLEAN First) +{ + PSYNC_ENTRY NewEntry; + IInterruptSyncImpl * This = (IInterruptSyncImpl*)iface; + + NewEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SYNC_ENTRY), TAG_PORTCLASS); + if (!NewEntry) + return STATUS_INSUFFICIENT_RESOURCES; + + NewEntry->SyncRoutine = Routine; + NewEntry->DynamicContext = DynamicContext; + + if (First) + InsertHeadList(&This->ServiceRoutines, &NewEntry->ListEntry); + else + InsertTailList(&This->ServiceRoutines, &NewEntry->ListEntry); + + return STATUS_SUCCESS; +} + +static IInterruptSyncVtbl vt_IInterruptSyncVtbl = +{ + /* IUnknown methods */ + IInterruptSync_fnQueryInterface, + IInterruptSync_fnAddRef, + IInterruptSync_fnRelease, + /* IInterruptSync methods */ + IInterruptSync_fnCallSynchronizedRoutine, + IInterruptSync_fnGetKInterrupt, + IInterruptSync_fnConnect, + IInterruptSync_fnDisconnect, + IInterruptSync_fnRegisterServiceRoutine +}; + +/* + * @unimplemented + */ +NTSTATUS NTAPI +PcNewInterruptSync( + OUT PINTERRUPTSYNC* OutInterruptSync, + IN PUNKNOWN OuterUnknown OPTIONAL, + IN PRESOURCELIST ResourceList, + IN ULONG ResourceIndex, + IN INTERRUPTSYNCMODE Mode) +{ + IInterruptSyncImpl * This; + + + if (!OutInterruptSync || !ResourceList || Mode > InterruptSyncModeRepeat || Mode < 0) + return STATUS_INVALID_PARAMETER; + + if (ResourceIndex > ResourceList->lpVtbl->NumberOfEntriesOfType(ResourceList, CmResourceTypeInterrupt)) + return STATUS_INVALID_PARAMETER; + + ResourceList->lpVtbl->AddRef(ResourceList); + + This = ExAllocatePoolWithTag(NonPagedPool, sizeof(IInterruptSyncImpl), TAG_PORTCLASS); + if (!This) + return STATUS_INSUFFICIENT_RESOURCES; + + This->lpVtbl = &vt_IInterruptSyncVtbl; + This->ref = 1; + This->Mode = Mode; + This->Interrupt = NULL; + This->ResourceIndex = ResourceIndex; + This->ResourceList = ResourceList; + InitializeListHead(&This->ServiceRoutines); + KeInitializeSpinLock(&This->Lock); + + *OutInterruptSync = (PINTERRUPTSYNC)&This->lpVtbl; + return STATUS_UNSUCCESSFUL; +} +
Propchange: trunk/reactos/drivers/wdm/audio/backpln/portcls/interrupt.c ------------------------------------------------------------------------------ svn:eol-style = native
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] Mon Dec 8 13:08:07 2008 @@ -15,6 +15,7 @@ <file>dma_slave.c</file> <file>adapter.c</file> <file>irp.c</file> + <file>interrupt.c</file> <file>drm.c</file> <file>stubs.c</file> <file>undoc.c</file>
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/stubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/stubs.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/stubs.c [iso-8859-1] Mon Dec 8 13:08:07 2008 @@ -23,21 +23,6 @@ IN POOL_TYPE PoolType, IN PDEVICE_DESCRIPTION DeviceDescription, IN PDEVICE_OBJECT DeviceObject) -{ - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; -} - -/* - * @unimplemented - */ -NTSTATUS NTAPI -PcNewInterruptSync( - OUT PINTERRUPTSYNC* OUtInterruptSync, - IN PUNKNOWN OuterUnknown OPTIONAL, - IN PRESOURCELIST ResourceList, - IN ULONG ResourceIndex, - IN INTERRUPTSYNCMODE Mode) { UNIMPLEMENTED; return STATUS_UNSUCCESSFUL;