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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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;