ReactOS 0.4.15-dev-6675-gcbc63d8
interrupt.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/amd64/interrupt.c
5 * PURPOSE: Manages the Kernel's IRQ support for external drivers,
6 * for the purpopses of connecting, disconnecting and setting
7 * up ISRs for drivers. The backend behind the Io* Interrupt
8 * routines.
9 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
10 * Alex Ionescu (alex.ionescu@reactos.org)
11 */
12
13/* INCLUDES *****************************************************************/
14
15#include <ntoskrnl.h>
16#define NDEBUG
17#include <debug.h>
18
23
24
25/* FUNCTIONS ****************************************************************/
26
27VOID
39 IN CHAR ProcessorNumber,
41{
42
43 /* Initialize the header */
45 Interrupt->Size = sizeof(KINTERRUPT);
46
47 /* If no Spinlock is given, use the internal */
48 if (!SpinLock) SpinLock = &Interrupt->SpinLock;
50
51 /* Set the given parameters */
52 Interrupt->ServiceRoutine = ServiceRoutine;
53 Interrupt->ServiceContext = ServiceContext;
54 Interrupt->ActualLock = SpinLock;
55 Interrupt->Vector = Vector;
56 Interrupt->Irql = Irql;
57 Interrupt->SynchronizeIrql = SynchronizeIrql;
59 Interrupt->ShareVector = ShareVector;
60 Interrupt->Number = ProcessorNumber;
61 Interrupt->FloatingSave = FloatingSave;
62
63 /* Set initial values */
64 Interrupt->TickCount = 0;
65 Interrupt->Connected = FALSE;
66 Interrupt->ServiceCount = 0;
67 Interrupt->DispatchCount = 0;
68 Interrupt->TrapFrame = NULL;
69 Interrupt->Reserved = 0;
70
71 /* Copy the dispatch code (its location independent, no need to patch it) */
72 RtlCopyMemory(Interrupt->DispatchCode,
74 sizeof(Interrupt->DispatchCode));
75
76 Interrupt->DispatchAddress = 0;
77}
78
82{
83 PVOID CurrentHandler;
84 PKINTERRUPT ConnectedInterrupt;
86
90 ASSERT(Interrupt->Irql <= HIGH_LEVEL);
91 ASSERT(Interrupt->SynchronizeIrql >= Interrupt->Irql);
92 ASSERT(Interrupt->Irql == (Interrupt->Vector >> 4));
93
94 /* Check if its already connected */
95 if (Interrupt->Connected) return TRUE;
96
97 /* Set the system affinity and acquire the dispatcher lock */
98 KeSetSystemAffinityThread(1ULL << Interrupt->Number);
100
101 /* Query the current handler */
102 CurrentHandler = KeQueryInterruptHandler(Interrupt->Vector);
103
104 /* Check if the vector is unused */
105 if ((CurrentHandler >= (PVOID)KiUnexpectedRange) &&
106 (CurrentHandler <= (PVOID)KiUnexpectedRangeEnd))
107 {
108 /* Initialize the list for chained interrupts */
109 InitializeListHead(&Interrupt->InterruptListEntry);
110
111 /* Set normal dispatch address */
112 Interrupt->DispatchAddress = KiInterruptDispatch;
113
114 /* Set the new handler */
116 Interrupt->DispatchCode);
117
118 /* Enable the interrupt */
120 Interrupt->Irql,
121 Interrupt->Mode))
122 {
123 /* Didn't work, restore old handler */
124 DPRINT1("HalEnableSystemInterrupt failed\n");
125 KeRegisterInterruptHandler(Interrupt->Vector, CurrentHandler);
126 goto Cleanup;
127 }
128 }
129 else
130 {
131 /* Get the connected interrupt */
132 ConnectedInterrupt = CONTAINING_RECORD(CurrentHandler, KINTERRUPT, DispatchCode);
133
134 /* Check if sharing is ok */
135 if ((Interrupt->ShareVector == 0) ||
136 (ConnectedInterrupt->ShareVector == 0) ||
137 (Interrupt->Mode != ConnectedInterrupt->Mode))
138 {
139 goto Cleanup;
140 }
141
142 /* Insert the new interrupt into the connected interrupt's list */
143 InsertTailList(&ConnectedInterrupt->InterruptListEntry,
144 &Interrupt->InterruptListEntry);
145 }
146
147 /* Mark as connected */
148 Interrupt->Connected = TRUE;
149
150Cleanup:
151 /* Release the dispatcher lock and restore the thread affinity */
154 return Interrupt->Connected;
155}
156
158NTAPI
160{
162 PVOID VectorHandler, UnexpectedHandler;
163 PKINTERRUPT VectorFirstInterrupt, NextInterrupt;
164 PLIST_ENTRY HandlerHead;
165
166 /* Set the system affinity and acquire the dispatcher lock */
167 KeSetSystemAffinityThread(1ULL << Interrupt->Number);
169
170 /* Check if the interrupt was connected - otherwise there's nothing to do */
171 if (Interrupt->Connected)
172 {
173 /* Get the handler for this interrupt vector */
174 VectorHandler = KeQueryInterruptHandler(Interrupt->Vector);
175
176 /* Get the first interrupt for this handler */
177 VectorFirstInterrupt = CONTAINING_RECORD(VectorHandler, KINTERRUPT, DispatchCode);
178
179 /* The first interrupt list entry is the interrupt list head */
180 HandlerHead = &VectorFirstInterrupt->InterruptListEntry;
181
182 /* If the list is empty, this is the only interrupt for this vector */
183 if (IsListEmpty(HandlerHead))
184 {
185 /* If the list is empty, and the head is not from this interrupt,
186 * this interrupt is somehow incorrectly connected */
187 ASSERT(VectorFirstInterrupt == Interrupt);
188
189 UnexpectedHandler = &KiUnexpectedRange[Interrupt->Vector]._Op_push;
190
191 /* This is the only interrupt, the handler can be disconnected */
193 KeRegisterInterruptHandler(Interrupt->Vector, UnexpectedHandler);
194 }
195 /* If the interrupt to be disconnected is the list head, but some others follow */
196 else if (VectorFirstInterrupt == Interrupt)
197 {
198 /* Relocate the head to the next element */
199 HandlerHead = HandlerHead->Flink;
200 RemoveTailList(HandlerHead);
201
202 /* Get the next interrupt from the list head */
203 NextInterrupt = CONTAINING_RECORD(HandlerHead,
205 InterruptListEntry);
206
207 /* Set the next interrupt as the handler for this vector */
209 NextInterrupt->DispatchCode);
210 }
211 /* If the interrupt to be disconnected is not the list head */
212 else
213 {
214 /* Remove the to be disconnected interrupt from the interrupt list */
215 RemoveEntryList(&Interrupt->InterruptListEntry);
216 }
217
218 /* Mark as not connected */
219 Interrupt->Connected = FALSE;
220 }
221
222 /* Release the dispatcher lock and restore the thread affinity */
225
226 return TRUE;
227}
228
230NTAPI
234{
237
238 /* Raise IRQL */
239 OldIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);
240
241 /* Acquire interrupt spinlock */
243
244 /* Call the routine */
246
247 /* Release lock */
249
250 /* Lower IRQL */
252
253 /* Return status */
254 return Success;
255}
static KSYNCHRONIZE_ROUTINE SynchronizeRoutine
Definition: IoInterrupt.c:30
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
_Out_ PKIRQL Irql
Definition: csq.h:179
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR Cleanup[]
Definition: register.c:80
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
KSPIN_LOCK * PKSPIN_LOCK
Definition: env_spec_w32.h:73
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
@ Success
Definition: eventcreate.c:712
BOOLEAN NTAPI HalEnableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode)
Definition: pic.c:295
VOID NTAPI HalDisableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql)
Definition: pic.c:309
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
#define PRIMARY_VECTOR_BASE
Definition: halp.h:16
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define ASSERT(a)
Definition: mode.c:44
#define MAXIMUM_IDTVECTOR
Definition: asm.h:280
struct _KINTERRUPT KINTERRUPT
@ InterruptObject
Definition: ketypes.h:461
FORCEINLINE PVOID KeQueryInterruptHandler(IN ULONG Vector)
Definition: ke.h:327
FORCEINLINE VOID KeRegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler)
Definition: ke.h:301
KI_INTERRUPT_DISPATCH_ENTRY KiUnexpectedRange[256]
BOOLEAN NTAPI KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
Definition: interrupt.c:159
BOOLEAN NTAPI KeConnectInterrupt(IN PKINTERRUPT Interrupt)
Definition: interrupt.c:81
void KiInterruptDispatch(void)
KI_INTERRUPT_DISPATCH_ENTRY KiUnexpectedRangeEnd[]
UCHAR KiInterruptDispatchTemplate[16]
VOID NTAPI KeInitializeInterrupt(IN PKINTERRUPT Interrupt, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN CHAR ProcessorNumber, IN BOOLEAN FloatingSave)
Definition: interrupt.c:29
BOOLEAN NTAPI KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, IN PVOID SynchronizeContext OPTIONAL)
Definition: interrupt.c:231
enum _KINTERRUPT_MODE KINTERRUPT_MODE
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
ULONG DispatchCode[DISPATCH_LENGTH]
Definition: ketypes.h:908
KINTERRUPT_MODE Mode
Definition: ketypes.h:895
BOOLEAN ShareVector
Definition: ketypes.h:894
LIST_ENTRY InterruptListEntry
Definition: ketypes.h:877
Definition: ke.h:103
UCHAR _Op_push
Definition: ke.h:105
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
VOID NTAPI KeSetSystemAffinityThread(IN KAFFINITY Affinity)
Definition: thrdobj.c:1116
VOID NTAPI KeRevertToUserAffinityThread(VOID)
Definition: thrdobj.c:1030
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFSPINLOCK * SpinLock
Definition: wdfsync.h:228
_In_ PKSERVICE_ROUTINE ServiceRoutine
Definition: iofuncs.h:800
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE InterruptMode
Definition: iofuncs.h:806
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL SynchronizeIrql
Definition: iofuncs.h:805
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE _In_ BOOLEAN _In_ KAFFINITY _In_ BOOLEAN FloatingSave
Definition: iofuncs.h:809
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE _In_ BOOLEAN ShareVector
Definition: iofuncs.h:807
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:801
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
_In_ PKSYNCHRONIZE_ROUTINE _In_opt_ __drv_aliasesMem PVOID SynchronizeContext
Definition: kefuncs.h:539
KSERVICE_ROUTINE * PKSERVICE_ROUTINE
Definition: ketypes.h:500
KSYNCHRONIZE_ROUTINE * PKSYNCHRONIZE_ROUTINE
Definition: ketypes.h:863
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175