- Implemented KeAcquireInterruptSpinLock and KeReleaseInterruptSpinLock.
[reactos.git] / reactos / ntoskrnl / io / irq.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/irq.c
5 * PURPOSE: IRQ handling
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <internal/debug.h>
14
15 /* GLOBALS *****************************************************************/
16
17 #define TAG_KINTERRUPT TAG('K', 'I', 'S', 'R')
18
19 /* FUNCTIONS *****************************************************************/
20
21 /*
22 * @implemented
23 */
24 NTSTATUS STDCALL
25 IoConnectInterrupt(PKINTERRUPT* InterruptObject,
26 PKSERVICE_ROUTINE ServiceRoutine,
27 PVOID ServiceContext,
28 PKSPIN_LOCK SpinLock,
29 ULONG Vector,
30 KIRQL Irql,
31 KIRQL SynchronizeIrql,
32 KINTERRUPT_MODE InterruptMode,
33 BOOLEAN ShareVector,
34 KAFFINITY ProcessorEnableMask,
35 BOOLEAN FloatingSave)
36 /*
37 * FUNCTION: Registers a driver's isr to be called when its device interrupts
38 * ARGUMENTS:
39 * InterruptObject (OUT) = Points to the interrupt object created on
40 * return
41 * ServiceRoutine = Routine to be called when the device interrupts
42 * ServiceContext = Parameter to be passed to ServiceRoutine
43 * SpinLock = Initalized spinlock that will be used to synchronize
44 * access between the isr and other driver routines. This is
45 * required if the isr handles more than one vector or the
46 * driver has more than one isr
47 * Vector = Interrupt vector to allocate
48 * (returned from HalGetInterruptVector)
49 * Irql = DIRQL returned from HalGetInterruptVector
50 * SynchronizeIrql = DIRQL at which the isr will execute. This must
51 * be the highest of all the DIRQLs returned from
52 * HalGetInterruptVector if the driver has multiple
53 * isrs
54 * InterruptMode = Specifies if the interrupt is LevelSensitive or
55 * Latched
56 * ShareVector = Specifies if the vector can be shared
57 * ProcessorEnableMask = Processors on the isr can run
58 * FloatingSave = TRUE if the floating point stack should be saved when
59 * the isr runs. Must be false for x86 drivers
60 * RETURNS: Status
61 * IRQL: PASSIVE_LEVEL
62 */
63 {
64 PKINTERRUPT Interrupt;
65 ULONG i, count;
66
67 ASSERT_IRQL(PASSIVE_LEVEL);
68
69 DPRINT("IoConnectInterrupt(Vector %x)\n",Vector);
70
71 ProcessorEnableMask &= ((1 << KeNumberProcessors) - 1);
72
73 if (ProcessorEnableMask == 0)
74 {
75 return STATUS_INVALID_PARAMETER;
76 }
77
78 for (i = 0, count = 0; i < KeNumberProcessors; i++)
79 {
80 if (ProcessorEnableMask & (1 << i))
81 {
82 count++;
83 }
84 }
85 /*
86 * Initialize interrupt object
87 */
88 Interrupt=ExAllocatePoolWithTag(NonPagedPool,count*sizeof(KINTERRUPT),
89 TAG_KINTERRUPT);
90 if (Interrupt==NULL)
91 {
92 return(STATUS_INSUFFICIENT_RESOURCES);
93 }
94
95 if (SpinLock == NULL)
96 {
97 SpinLock = &Interrupt[0].SpinLock;
98 KeInitializeSpinLock(SpinLock);
99 }
100
101 Interrupt[0].ProcessorEnableMask = ProcessorEnableMask;
102
103 for (i = 0, count = 0; i < KeNumberProcessors; i++)
104 {
105 if (ProcessorEnableMask & (1 << i))
106 {
107 KeInitializeInterrupt(&Interrupt[count],
108 ServiceRoutine,
109 ServiceContext,
110 SpinLock,
111 Vector,
112 Irql,
113 SynchronizeIrql,
114 InterruptMode,
115 ShareVector,
116 i,
117 FloatingSave);
118 if (!KeConnectInterrupt(&Interrupt[count]))
119 {
120 for (i = 0; i < count; i++)
121 {
122 KeDisconnectInterrupt(&Interrupt[i]);
123 }
124 ExFreePool(Interrupt);
125 return STATUS_INVALID_PARAMETER;
126 }
127 count++;
128 }
129 }
130
131 *InterruptObject = Interrupt;
132
133 return(STATUS_SUCCESS);
134 }
135
136
137 /*
138 * @implemented
139 */
140 VOID STDCALL
141 IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
142 /*
143 * FUNCTION: Releases a drivers isr
144 * ARGUMENTS:
145 * InterruptObject = isr to release
146 */
147 {
148 ULONG i, count;
149
150 for (i = 0, count = 0; i < KeNumberProcessors; i++)
151 {
152 if (InterruptObject[0].ProcessorEnableMask & (1 << i))
153 {
154 KeDisconnectInterrupt(&InterruptObject[count]);
155 count++;
156 }
157 }
158 ExFreePool(InterruptObject);
159 }
160
161 /* EOF */