ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

interrupt.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/wdm/audio/backpln/portcls/interrupt.cpp
00005  * PURPOSE:         portcls interrupt object
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "private.hpp"
00011 
00012 typedef struct
00013 {
00014     LIST_ENTRY ListEntry;
00015     PINTERRUPTSYNCROUTINE SyncRoutine;
00016     PVOID DynamicContext;
00017 }SYNC_ENTRY, *PSYNC_ENTRY;
00018 
00019 class CInterruptSync : public IInterruptSync
00020 {
00021 public:
00022     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00023 
00024     STDMETHODIMP_(ULONG) AddRef()
00025     {
00026         InterlockedIncrement(&m_Ref);
00027         return m_Ref;
00028     }
00029     STDMETHODIMP_(ULONG) Release()
00030     {
00031         InterlockedDecrement(&m_Ref);
00032 
00033         if (!m_Ref)
00034         {
00035             delete this;
00036             return 0;
00037         }
00038         return m_Ref;
00039     }
00040     IMP_IInterruptSync;
00041     CInterruptSync(IUnknown *OuterUnknown){}
00042     virtual ~CInterruptSync(){}
00043 
00044 public:
00045 
00046     KSPIN_LOCK m_Lock;
00047     LIST_ENTRY m_ServiceRoutines;
00048     PKINTERRUPT m_Interrupt;
00049     INTERRUPTSYNCMODE m_Mode;
00050     PRESOURCELIST m_ResourceList;
00051     ULONG m_ResourceIndex;
00052 
00053     PINTERRUPTSYNCROUTINE m_SyncRoutine;
00054     PVOID m_DynamicContext;
00055     NTSTATUS m_Status;
00056 
00057     LONG m_Ref;
00058 
00059     friend BOOLEAN NTAPI CInterruptSynchronizedRoutine(IN PVOID  ServiceContext);
00060     friend BOOLEAN NTAPI IInterruptServiceRoutine(IN PKINTERRUPT  Interrupt, IN PVOID  ServiceContext);
00061 };
00062 
00063 
00064 //---------------------------------------------------------------
00065 // IUnknown methods
00066 //
00067 
00068 
00069 
00070 NTSTATUS
00071 NTAPI
00072 CInterruptSync::QueryInterface(
00073     IN  REFIID refiid,
00074     OUT PVOID* Output)
00075 {
00076     UNICODE_STRING GuidString;
00077 
00078     DPRINT("CInterruptSync::QueryInterface: this %p\n", this);
00079 
00080     if (IsEqualGUIDAligned(refiid, IID_IInterruptSync) ||
00081         IsEqualGUIDAligned(refiid, IID_IUnknown))
00082     {
00083         *Output = PVOID(PUNKNOWN(this));
00084         PUNKNOWN(*Output)->AddRef();
00085         return STATUS_SUCCESS;
00086     }
00087 
00088 
00089     if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
00090     {
00091         DPRINT1("CInterruptSync::QueryInterface: no interface!!! iface %S\n", GuidString.Buffer);
00092         RtlFreeUnicodeString(&GuidString);
00093     }
00094 
00095     return STATUS_UNSUCCESSFUL;
00096 }
00097 
00098 //---------------------------------------------------------------
00099 // CInterruptSync methods
00100 //
00101 
00102 
00103 BOOLEAN
00104 NTAPI
00105 CInterruptSynchronizedRoutine(
00106     IN PVOID  ServiceContext)
00107 {
00108     CInterruptSync * This = (CInterruptSync*)ServiceContext;
00109     This->m_Status = This->m_SyncRoutine(This, This->m_DynamicContext);
00110 
00111     DPRINT("CInterruptSynchronizedRoutine this %p SyncRoutine %p Context %p Status %x\n", This, This->m_SyncRoutine, This->m_DynamicContext, This->m_Status);
00112     return TRUE;
00113 }
00114 
00115 NTSTATUS
00116 NTAPI
00117 CInterruptSync::CallSynchronizedRoutine(
00118     IN PINTERRUPTSYNCROUTINE Routine,
00119     IN PVOID DynamicContext)
00120 {
00121     KIRQL OldIrql;
00122 
00123     DPRINT("CInterruptSync::CallSynchronizedRoutine this %p Routine %p DynamicContext %p Irql %x Interrupt %p\n", this, Routine, DynamicContext, KeGetCurrentIrql(), m_Interrupt);
00124     
00125     if (!m_Interrupt)
00126     {
00127         DPRINT("CInterruptSync_CallSynchronizedRoutine %p no interrupt connected\n", this);
00128         if (KeGetCurrentIrql() > DISPATCH_LEVEL)
00129             return STATUS_UNSUCCESSFUL;
00130 
00131         KeAcquireSpinLock(&m_Lock, &OldIrql);
00132         m_SyncRoutine = Routine;
00133         m_DynamicContext = DynamicContext;
00134         CInterruptSynchronizedRoutine((PVOID)this);
00135         KeReleaseSpinLock(&m_Lock, OldIrql);
00136 
00137         return m_Status;
00138     }
00139 
00140     m_SyncRoutine = Routine;
00141     m_DynamicContext = DynamicContext;
00142 
00143     if (KeSynchronizeExecution(m_Interrupt, CInterruptSynchronizedRoutine, (PVOID)this))
00144         return m_Status;
00145     else
00146         return STATUS_UNSUCCESSFUL;
00147 }
00148 
00149 PKINTERRUPT
00150 NTAPI
00151 CInterruptSync::GetKInterrupt()
00152 {
00153     DPRINT("CInterruptSynchronizedRoutine\n");
00154 
00155     return m_Interrupt;
00156 }
00157 
00158 BOOLEAN
00159 NTAPI
00160 IInterruptServiceRoutine(
00161     IN PKINTERRUPT  Interrupt,
00162     IN PVOID  ServiceContext)
00163 {
00164     PLIST_ENTRY CurEntry;
00165     PSYNC_ENTRY Entry;
00166     NTSTATUS Status;
00167     BOOL Success;
00168 
00169     CInterruptSync * This = (CInterruptSync*)ServiceContext;
00170 
00171     DPRINT("IInterruptServiceRoutine Mode %u\n", This->m_Mode);
00172 
00173     if (This->m_Mode == InterruptSyncModeNormal)
00174     {
00175         CurEntry = This->m_ServiceRoutines.Flink;
00176         while (CurEntry != &This->m_ServiceRoutines)
00177         {
00178             Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
00179             Status = Entry->SyncRoutine((CInterruptSync*)This, Entry->DynamicContext);
00180             if (NT_SUCCESS(Status))
00181             {
00182                 return TRUE;
00183             }
00184             CurEntry = CurEntry->Flink;
00185         }
00186         return FALSE;
00187     }
00188     else if (This->m_Mode == InterruptSyncModeAll)
00189     {
00190         CurEntry = This->m_ServiceRoutines.Flink;
00191         while (CurEntry != &This->m_ServiceRoutines)
00192         {
00193             Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
00194             Entry->SyncRoutine((CInterruptSync*)This, Entry->DynamicContext);
00195             CurEntry = CurEntry->Flink;
00196         }
00197         DPRINT("Returning TRUE with mode InterruptSyncModeAll\n");
00198         return TRUE; //FIXME
00199     }
00200     else if (This->m_Mode == InterruptSyncModeRepeat)
00201     {
00202         do
00203         {
00204             Success = FALSE;
00205             CurEntry = This->m_ServiceRoutines.Flink;
00206             while (CurEntry != &This->m_ServiceRoutines)
00207             {
00208                 Entry = CONTAINING_RECORD(CurEntry, SYNC_ENTRY, ListEntry);
00209                 Status = Entry->SyncRoutine((CInterruptSync*)This, Entry->DynamicContext);
00210                 if (NT_SUCCESS(Status))
00211                     Success = TRUE;
00212                 CurEntry = CurEntry->Flink;
00213             }
00214         }while(Success);
00215         DPRINT("Returning TRUE with mode InterruptSyncModeRepeat\n");
00216         return TRUE; //FIXME
00217     }
00218     else
00219     {
00220         DPRINT("Unknown mode %u\n", This->m_Mode);
00221         return FALSE; //FIXME
00222     }
00223 }
00224 
00225 
00226 NTSTATUS
00227 NTAPI
00228 CInterruptSync::Connect()
00229 {
00230     NTSTATUS Status;
00231     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
00232 
00233     DPRINT("CInterruptSync::Connect\n");
00234     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
00235 
00236     Descriptor = m_ResourceList->FindTranslatedEntry(CmResourceTypeInterrupt, m_ResourceIndex);
00237     if (!Descriptor)
00238         return STATUS_UNSUCCESSFUL;
00239 
00240     if (IsListEmpty(&m_ServiceRoutines))
00241         return STATUS_UNSUCCESSFUL;
00242 
00243     DPRINT1("Vector %u Level %u Flags %x Affinity %x\n", Descriptor->u.Interrupt.Vector, Descriptor->u.Interrupt.Level, Descriptor->Flags, Descriptor->u.Interrupt.Affinity);
00244 
00245     Status = IoConnectInterrupt(&m_Interrupt,
00246                                 IInterruptServiceRoutine,
00247                                 (PVOID)this,
00248                                 NULL, //&m_Lock,
00249                                 Descriptor->u.Interrupt.Vector,
00250                                 (KIRQL)Descriptor->u.Interrupt.Level,
00251                                 (KIRQL)Descriptor->u.Interrupt.Level,
00252                                 (KINTERRUPT_MODE)(Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
00253                                 (Descriptor->ShareDisposition != CmResourceShareDeviceExclusive),
00254                                 Descriptor->u.Interrupt.Affinity,
00255                                 FALSE);
00256 
00257     DPRINT1("CInterruptSync::Connect result %x\n", Status);
00258     return Status;
00259 }
00260 
00261 
00262 VOID
00263 NTAPI
00264 CInterruptSync::Disconnect()
00265 {
00266     DPRINT("CInterruptSync::Disconnect\n");
00267     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
00268 
00269     if (!m_Interrupt)
00270     {
00271         DPRINT("CInterruptSync_Disconnect %p no interrupt connected\n", this);
00272         return;
00273     }
00274 
00275     IoDisconnectInterrupt(m_Interrupt);
00276     m_Interrupt = NULL;
00277 }
00278 
00279 NTSTATUS
00280 NTAPI
00281 CInterruptSync::RegisterServiceRoutine(
00282     IN      PINTERRUPTSYNCROUTINE   Routine,
00283     IN      PVOID                   DynamicContext,
00284     IN      BOOLEAN                 First)
00285 {
00286     PSYNC_ENTRY NewEntry;
00287 
00288     DPRINT("CInterruptSync::RegisterServiceRoutine\n");
00289     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
00290 
00291     NewEntry = (PSYNC_ENTRY)AllocateItem(NonPagedPool, sizeof(SYNC_ENTRY), TAG_PORTCLASS);
00292     if (!NewEntry)
00293         return STATUS_INSUFFICIENT_RESOURCES;
00294 
00295     NewEntry->SyncRoutine = Routine;
00296     NewEntry->DynamicContext = DynamicContext;
00297 
00298     if (First)
00299         InsertHeadList(&m_ServiceRoutines, &NewEntry->ListEntry);
00300     else
00301         InsertTailList(&m_ServiceRoutines, &NewEntry->ListEntry);
00302 
00303     return STATUS_SUCCESS;
00304 }
00305 
00306 NTSTATUS
00307 NTAPI
00308 PcNewInterruptSync(
00309     OUT PINTERRUPTSYNC* OutInterruptSync,
00310     IN  PUNKNOWN OuterUnknown OPTIONAL,
00311     IN  PRESOURCELIST ResourceList,
00312     IN  ULONG ResourceIndex,
00313     IN  INTERRUPTSYNCMODE Mode)
00314 {
00315     CInterruptSync * This;
00316     NTSTATUS Status;
00317 
00318     DPRINT("PcNewInterruptSync entered OutInterruptSync %p OuterUnknown %p ResourceList %p ResourceIndex %u Mode %d\n", 
00319             OutInterruptSync, OuterUnknown, ResourceList, ResourceIndex, Mode);
00320 
00321     if (!OutInterruptSync || !ResourceList || Mode < InterruptSyncModeNormal || Mode > InterruptSyncModeRepeat)
00322         return STATUS_INVALID_PARAMETER;
00323 
00324     if (ResourceIndex > ResourceList->NumberOfEntriesOfType(CmResourceTypeInterrupt))
00325         return STATUS_INVALID_PARAMETER;
00326 
00327     This = new(NonPagedPool, TAG_PORTCLASS)CInterruptSync(OuterUnknown);
00328     if (!This)
00329         return STATUS_INSUFFICIENT_RESOURCES;
00330 
00331     Status = This->QueryInterface(IID_IInterruptSync, (PVOID*)OutInterruptSync);
00332 
00333     if (!NT_SUCCESS(Status))
00334     {
00335         delete This;
00336         return Status;
00337     }
00338 
00339     ResourceList->AddRef();
00340 
00341     //
00342     // initialize object
00343     //
00344     This->m_Mode = Mode;
00345     This->m_ResourceIndex = ResourceIndex;
00346     This->m_ResourceList = ResourceList;
00347     InitializeListHead(&This->m_ServiceRoutines);
00348     KeInitializeSpinLock(&This->m_Lock);
00349 
00350     return Status;
00351 }

Generated on Sun May 27 2012 04:28:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.