Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninterrupt.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
1.7.6.1
|