6 PINTERRUPTSYNCROUTINE SyncRoutine
;
8 }SYNC_ENTRY
, *PSYNC_ENTRY
;
12 IInterruptSyncVtbl
*lpVtbl
;
16 LIST_ENTRY ServiceRoutines
;
17 PKINTERRUPT Interrupt
;
18 INTERRUPTSYNCMODE Mode
;
19 PRESOURCELIST ResourceList
;
22 PINTERRUPTSYNCROUTINE SyncRoutine
;
27 //---------------------------------------------------------------
35 IInterruptSync_fnQueryInterface(
36 IInterruptSync
* iface
,
40 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
42 DPRINT1("IInterruptSync_fnQueryInterface: This %p\n", This
);
44 if (IsEqualGUIDAligned(refiid
, &IID_IInterruptSync
))
46 *Output
= &This
->lpVtbl
;
47 _InterlockedIncrement(&This
->ref
);
48 return STATUS_SUCCESS
;
50 DPRINT1("IInterruptSync_fnQueryInterface: This %p UNKNOWN interface requested\n", This
);
51 return STATUS_UNSUCCESSFUL
;
56 IInterruptSync_fnAddRef(
57 IInterruptSync
* iface
)
59 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
61 DPRINT1("IInterruptSync_AddRef: This %p\n", This
);
63 return _InterlockedIncrement(&This
->ref
);
68 IInterruptSync_fnRelease(
69 IInterruptSync
* iface
)
73 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
75 _InterlockedDecrement(&This
->ref
);
77 DPRINT1("IInterruptSync_Release: This %p new ref %u\n", This
, This
->ref
);
81 while(!IsListEmpty(&This
->ServiceRoutines
))
83 CurEntry
= RemoveHeadList(&This
->ServiceRoutines
);
84 Entry
= CONTAINING_RECORD(CurEntry
, SYNC_ENTRY
, ListEntry
);
85 FreeItem(Entry
, TAG_PORTCLASS
);
88 //This->ResourceList->lpVtbl->Release(This->ResourceList);
89 //FreeItem(This, TAG_PORTCLASS);
90 DPRINT1("IInterruptSync_Release: complete\n");
93 /* Return new reference count */
97 //---------------------------------------------------------------
98 // IInterruptSync methods
104 IInterruptSynchronizedRoutine(
105 IN PVOID ServiceContext
)
107 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)ServiceContext
;
108 DPRINT1("IInterruptSynchronizedRoutine This %p SyncRoutine%p\n", This
, This
->SyncRoutine
);
109 return This
->SyncRoutine((IInterruptSync
*)&This
->lpVtbl
, This
->DynamicContext
);
114 IInterruptSync_fnCallSynchronizedRoutine(
115 IN IInterruptSync
* iface
,
116 IN PINTERRUPTSYNCROUTINE Routine
,
117 IN PVOID DynamicContext
)
120 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
122 DPRINT1("IInterruptSync_fnCallSynchronizedRoutine This %p Routine %p DynamicContext %p\n", This
, Routine
, DynamicContext
);
124 if (!This
->Interrupt
)
126 DPRINT("IInterruptSync_CallSynchronizedRoutine %p no interrupt connected\n", This
);
127 if (KeGetCurrentIrql() > DISPATCH_LEVEL
)
128 return STATUS_UNSUCCESSFUL
;
130 KeAcquireSpinLock(&This
->Lock
, &OldIrql
);
131 This
->SyncRoutine
= Routine
;
132 This
->DynamicContext
= DynamicContext
;
133 IInterruptSynchronizedRoutine((PVOID
)This
);
134 KeReleaseSpinLock(&This
->Lock
, OldIrql
);
136 return STATUS_SUCCESS
;
139 This
->SyncRoutine
= Routine
;
140 This
->DynamicContext
= DynamicContext
;
142 return KeSynchronizeExecution(This
->Interrupt
, IInterruptSynchronizedRoutine
, (PVOID
)This
);
147 IInterruptSync_fnGetKInterrupt(
148 IN IInterruptSync
* iface
)
150 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
151 DPRINT1("IInterruptSynchronizedRoutine\n");
153 return This
->Interrupt
;
158 IInterruptServiceRoutine(
159 IN PKINTERRUPT Interrupt
,
160 IN PVOID ServiceContext
)
162 PLIST_ENTRY CurEntry
;
166 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)ServiceContext
;
168 DPRINT1("IInterruptServiceRoutine\n");
170 if (This
->Mode
== InterruptSyncModeNormal
)
172 CurEntry
= This
->ServiceRoutines
.Flink
;
173 while (CurEntry
!= &This
->ServiceRoutines
)
175 Entry
= CONTAINING_RECORD(CurEntry
, SYNC_ENTRY
, ListEntry
);
176 Status
= Entry
->SyncRoutine((IInterruptSync
*)This
, Entry
->DynamicContext
);
177 if (NT_SUCCESS(Status
))
181 CurEntry
= CurEntry
->Flink
;
185 else if (This
->Mode
== InterruptSyncModeAll
)
187 CurEntry
= This
->ServiceRoutines
.Flink
;
188 while (CurEntry
!= &This
->ServiceRoutines
)
190 Entry
= CONTAINING_RECORD(CurEntry
, SYNC_ENTRY
, ListEntry
);
191 Status
= Entry
->SyncRoutine((IInterruptSync
*)This
, Entry
->DynamicContext
);
192 CurEntry
= CurEntry
->Flink
;
194 DPRINT("Returning TRUE with mode InterruptSyncModeAll\n");
197 else if (This
->Mode
== InterruptSyncModeRepeat
)
202 CurEntry
= This
->ServiceRoutines
.Flink
;
203 while (CurEntry
!= &This
->ServiceRoutines
)
205 Entry
= CONTAINING_RECORD(CurEntry
, SYNC_ENTRY
, ListEntry
);
206 Status
= Entry
->SyncRoutine((IInterruptSync
*)This
, Entry
->DynamicContext
);
207 if (NT_SUCCESS(Status
))
209 CurEntry
= CurEntry
->Flink
;
212 DPRINT("Returning TRUE with mode InterruptSyncModeRepeat\n");
217 DPRINT("Unknown mode %u\n", This
->Mode
);
218 return FALSE
; //FIXME
225 IInterruptSync_fnConnect(
226 IN IInterruptSync
* iface
)
228 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
230 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
232 DPRINT1("IInterruptSync_fnConnect\n");
234 Descriptor
= This
->ResourceList
->lpVtbl
->FindTranslatedEntry(This
->ResourceList
, CmResourceTypeInterrupt
, This
->ResourceIndex
);
236 return STATUS_UNSUCCESSFUL
;
238 if (IsListEmpty(&This
->ServiceRoutines
))
239 return STATUS_UNSUCCESSFUL
;
241 Status
= IoConnectInterrupt(&This
->Interrupt
,
242 IInterruptServiceRoutine
,
244 &This
->Lock
, Descriptor
->u
.Interrupt
.Vector
,
245 Descriptor
->u
.Interrupt
.Level
,
246 Descriptor
->u
.Interrupt
.Level
, //FIXME
247 LevelSensitive
, //FIXME
249 Descriptor
->u
.Interrupt
.Affinity
,
258 IInterruptSync_fnDisconnect(
259 IN IInterruptSync
* iface
)
261 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
262 DPRINT1("IInterruptSync_fnDisconnect\n");
264 if (!This
->Interrupt
)
266 DPRINT("IInterruptSync_Disconnect %p no interrupt connected\n", This
);
270 IoDisconnectInterrupt(This
->Interrupt
);
271 This
->Interrupt
= NULL
;
276 IInterruptSync_fnRegisterServiceRoutine(
277 IN IInterruptSync
* iface
,
278 IN PINTERRUPTSYNCROUTINE Routine
,
279 IN PVOID DynamicContext
,
282 PSYNC_ENTRY NewEntry
;
283 IInterruptSyncImpl
* This
= (IInterruptSyncImpl
*)iface
;
285 DPRINT1("IInterruptSync_fnRegisterServiceRoutine\n");
287 NewEntry
= AllocateItem(NonPagedPool
, sizeof(SYNC_ENTRY
), TAG_PORTCLASS
);
289 return STATUS_INSUFFICIENT_RESOURCES
;
291 NewEntry
->SyncRoutine
= Routine
;
292 NewEntry
->DynamicContext
= DynamicContext
;
295 InsertHeadList(&This
->ServiceRoutines
, &NewEntry
->ListEntry
);
297 InsertTailList(&This
->ServiceRoutines
, &NewEntry
->ListEntry
);
299 return STATUS_SUCCESS
;
302 static IInterruptSyncVtbl vt_IInterruptSyncVtbl
=
304 /* IUnknown methods */
305 IInterruptSync_fnQueryInterface
,
306 IInterruptSync_fnAddRef
,
307 IInterruptSync_fnRelease
,
308 /* IInterruptSync methods */
309 IInterruptSync_fnCallSynchronizedRoutine
,
310 IInterruptSync_fnGetKInterrupt
,
311 IInterruptSync_fnConnect
,
312 IInterruptSync_fnDisconnect
,
313 IInterruptSync_fnRegisterServiceRoutine
321 OUT PINTERRUPTSYNC
* OutInterruptSync
,
322 IN PUNKNOWN OuterUnknown OPTIONAL
,
323 IN PRESOURCELIST ResourceList
,
324 IN ULONG ResourceIndex
,
325 IN INTERRUPTSYNCMODE Mode
)
327 IInterruptSyncImpl
* This
;
329 DPRINT1("PcNewInterruptSync entered\n");
331 if (!OutInterruptSync
|| !ResourceList
|| Mode
> InterruptSyncModeRepeat
|| Mode
< 0)
332 return STATUS_INVALID_PARAMETER
;
334 if (ResourceIndex
> ResourceList
->lpVtbl
->NumberOfEntriesOfType(ResourceList
, CmResourceTypeInterrupt
))
335 return STATUS_INVALID_PARAMETER
;
338 ResourceList
->lpVtbl
->AddRef(ResourceList
);
340 This
= AllocateItem(NonPagedPool
, sizeof(IInterruptSyncImpl
), TAG_PORTCLASS
);
342 return STATUS_INSUFFICIENT_RESOURCES
;
344 /* initialize object */
345 This
->lpVtbl
= &vt_IInterruptSyncVtbl
;
348 This
->ResourceIndex
= ResourceIndex
;
349 This
->ResourceList
= ResourceList
;
350 InitializeListHead(&This
->ServiceRoutines
);
351 KeInitializeSpinLock(&This
->Lock
);
353 *OutInterruptSync
= (PINTERRUPTSYNC
)&This
->lpVtbl
;
354 DPRINT1("PcNewInterruptSync success %p\n", *OutInterruptSync
);
355 return STATUS_SUCCESS
;