ReactOS  0.4.15-dev-3163-gf17c2c0
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 
20 extern UCHAR KiUnexpectedRange[];
22 void KiInterruptDispatch(void);
23 
24 
25 /* FUNCTIONS ****************************************************************/
26 
27 VOID
28 NTAPI
34  IN ULONG Vector,
35  IN KIRQL Irql,
39  IN CHAR ProcessorNumber,
41 {
42 
43  /* Initialize the header */
44  Interrupt->Type = InterruptObject;
45  Interrupt->Size = sizeof(KINTERRUPT);
46 
47  /* If no Spinlock is given, use the internal */
48  if (!SpinLock) SpinLock = &Interrupt->SpinLock;
49  KeInitializeSpinLock(&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;
58  Interrupt->Mode = InterruptMode;
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 
79 BOOLEAN
80 NTAPI
82 {
83  PVOID CurrentHandler;
84  PKINTERRUPT ConnectedInterrupt;
85 
89  ASSERT(Interrupt->Irql <= HIGH_LEVEL);
90  ASSERT(Interrupt->SynchronizeIrql >= Interrupt->Irql);
91  ASSERT(Interrupt->Irql == (Interrupt->Vector >> 4));
92 
93  /* Check if its already connected */
94  if (Interrupt->Connected) return TRUE;
95 
96  /* Query the current handler */
97  CurrentHandler = KeQueryInterruptHandler(Interrupt->Vector);
98 
99  /* Check if the vector is unused */
100  if ((CurrentHandler >= (PVOID)KiUnexpectedRange) &&
101  (CurrentHandler <= (PVOID)KiUnexpectedRangeEnd))
102  {
103  /* Initialize the list for chained interrupts */
104  InitializeListHead(&Interrupt->InterruptListEntry);
105 
106  /* Set normal dispatch address */
107  Interrupt->DispatchAddress = KiInterruptDispatch;
108 
109  /* Set the new handler */
111  Interrupt->DispatchCode);
112 
113  /* Enable the interrupt */
114  if (!HalEnableSystemInterrupt(Interrupt->Vector,
115  Interrupt->Irql,
116  Interrupt->Mode))
117  {
118  /* Didn't work, restore old handler */
119  DPRINT1("HalEnableSystemInterrupt failed\n");
120  KeRegisterInterruptHandler(Interrupt->Vector, CurrentHandler);
121  return FALSE;
122  }
123  }
124  else
125  {
126  /* Get the connected interrupt */
127  ConnectedInterrupt = CONTAINING_RECORD(CurrentHandler, KINTERRUPT, DispatchCode);
128 
129  /* Check if sharing is ok */
130  if ((Interrupt->ShareVector == 0) ||
131  (ConnectedInterrupt->ShareVector == 0) ||
132  (Interrupt->Mode != ConnectedInterrupt->Mode))
133  {
134  return FALSE;
135  }
136 
137  /* Insert the new interrupt into the connected interrupt's list */
138  InsertTailList(&ConnectedInterrupt->InterruptListEntry,
139  &Interrupt->InterruptListEntry);
140  }
141 
142  /* Mark as connected */
143  Interrupt->Connected = TRUE;
144 
145  return TRUE;
146 }
147 
148 BOOLEAN
149 NTAPI
151 {
152  /* If the interrupt wasn't connected, there's nothing to do */
153  if (!Interrupt->Connected)
154  {
155  return FALSE;
156  }
157 
159  __debugbreak();
160  return TRUE;
161 }
162 
163 BOOLEAN
164 NTAPI
168 {
170  KIRQL OldIrql;
171 
172  /* Raise IRQL */
173  OldIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);
174 
175  /* Acquire interrupt spinlock */
177 
178  /* Call the routine */
180 
181  /* Release lock */
183 
184  /* Lower IRQL */
186 
187  /* Return status */
188  return Success;
189 }
#define IN
Definition: typedefs.h:39
BOOLEAN NTAPI HalEnableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode)
Definition: pic.c:295
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE InterruptMode
Definition: iofuncs.h:800
UCHAR KiInterruptDispatchTemplate[16]
UCHAR KiUnexpectedRange[]
#define TRUE
Definition: types.h:120
_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:800
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:372
char CHAR
Definition: xmlstorage.h:175
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:198
#define PRIMARY_VECTOR_BASE
Definition: halp.h:16
KSPIN_LOCK * PKSPIN_LOCK
Definition: env_spec_w32.h:73
#define InsertTailList(ListHead, Entry)
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
_Out_ PKIRQL Irql
Definition: csq.h:179
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
FORCEINLINE PVOID KeQueryInterruptHandler(IN ULONG Vector)
Definition: ke.h:323
KINTERRUPT_MODE Mode
Definition: ketypes.h:887
KSERVICE_ROUTINE * PKSERVICE_ROUTINE
Definition: ketypes.h:500
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFSPINLOCK * SpinLock
Definition: wdfsync.h:225
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
unsigned char BOOLEAN
enum _KINTERRUPT_MODE KINTERRUPT_MODE
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL SynchronizeIrql
Definition: iofuncs.h:800
KSYNCHRONIZE_ROUTINE * PKSYNCHRONIZE_ROUTINE
Definition: ketypes.h:863
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
KIRQL OldIrql
Definition: mm.h:1502
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
LIST_ENTRY InterruptListEntry
Definition: ketypes.h:869
_In_ PKSYNCHRONIZE_ROUTINE SynchronizeRoutine
Definition: kefuncs.h:536
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:221
BOOLEAN ShareVector
Definition: ketypes.h:886
BOOLEAN NTAPI KeConnectInterrupt(IN PKINTERRUPT Interrupt)
Definition: interrupt.c:81
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:800
unsigned char UCHAR
Definition: xmlstorage.h:181
_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:800
BOOLEAN NTAPI KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
Definition: interrupt.c:150
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
FORCEINLINE VOID KeRegisterInterruptHandler(IN ULONG Vector, IN PVOID Handler)
Definition: ke.h:297
_In_ PKSYNCHRONIZE_ROUTINE _In_opt_ __drv_aliasesMem PVOID SynchronizeContext
Definition: kefuncs.h:536
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG Vector
Definition: iofuncs.h:800
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
UCHAR KiUnexpectedRangeEnd[]
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:40
struct _KINTERRUPT KINTERRUPT
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:115
BOOLEAN NTAPI KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, IN PVOID SynchronizeContext OPTIONAL)
Definition: interrupt.c:165
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
void KiInterruptDispatch(void)
#define MAXIMUM_IDTVECTOR
Definition: asm.h:280
_In_ PKSERVICE_ROUTINE ServiceRoutine
Definition: iofuncs.h:800
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68