Reintegrate header branch
[reactos.git] / reactos / ntoskrnl / io / iomgr / irq.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/irq.c
5 * PURPOSE: I/O Wrappers (called Completion Ports) for Kernel Queues
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 /*
18 * @implemented
19 */
20 NTSTATUS
21 NTAPI
22 IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject,
23 IN PKSERVICE_ROUTINE ServiceRoutine,
24 IN PVOID ServiceContext,
25 IN PKSPIN_LOCK SpinLock,
26 IN ULONG Vector,
27 IN KIRQL Irql,
28 IN KIRQL SynchronizeIrql,
29 IN KINTERRUPT_MODE InterruptMode,
30 IN BOOLEAN ShareVector,
31 IN KAFFINITY ProcessorEnableMask,
32 IN BOOLEAN FloatingSave)
33 {
34 PKINTERRUPT Interrupt;
35 PKINTERRUPT InterruptUsed;
36 PIO_INTERRUPT IoInterrupt;
37 PKSPIN_LOCK SpinLockUsed;
38 BOOLEAN FirstRun;
39 CCHAR Count = 0;
40 KAFFINITY Affinity;
41 PAGED_CODE();
42
43 /* Assume failure */
44 *InterruptObject = NULL;
45
46 /* Get the affinity */
47 Affinity = ProcessorEnableMask & KeActiveProcessors;
48 while (Affinity)
49 {
50 /* Increase count */
51 if (Affinity & 1) Count++;
52 Affinity >>= 1;
53 }
54
55 /* Make sure we have a valid CPU count */
56 if (!Count) return STATUS_INVALID_PARAMETER;
57
58 /* Allocate the array of I/O Interrupts */
59 IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,
60 (Count - 1) * sizeof(KINTERRUPT) +
61 sizeof(IO_INTERRUPT),
62 TAG_KINTERRUPT);
63 if (!IoInterrupt) return STATUS_INSUFFICIENT_RESOURCES;
64
65 /* Select which Spinlock to use */
66 SpinLockUsed = SpinLock ? SpinLock : &IoInterrupt->SpinLock;
67
68 /* We first start with a built-in Interrupt inside the I/O Structure */
69 *InterruptObject = &IoInterrupt->FirstInterrupt;
70 Interrupt = (PKINTERRUPT)(IoInterrupt + 1);
71 FirstRun = TRUE;
72
73 /* Start with a fresh structure */
74 RtlZeroMemory(IoInterrupt, sizeof(IO_INTERRUPT));
75
76 /* Now create all the interrupts */
77 Affinity = ProcessorEnableMask & KeActiveProcessors;
78 for (Count = 0; Affinity; Count++, Affinity >>= 1)
79 {
80 /* Check if it's enabled for this CPU */
81 if (Affinity & 1)
82 {
83 /* Check which one we will use */
84 InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;
85
86 /* Initialize it */
87 KeInitializeInterrupt(InterruptUsed,
88 ServiceRoutine,
89 ServiceContext,
90 SpinLockUsed,
91 Vector,
92 Irql,
93 SynchronizeIrql,
94 InterruptMode,
95 ShareVector,
96 Count,
97 FloatingSave);
98
99 /* Connect it */
100 if (!KeConnectInterrupt(InterruptUsed))
101 {
102 /* Check how far we got */
103 if (FirstRun)
104 {
105 /* We failed early so just free this */
106 ExFreePool(IoInterrupt);
107 }
108 else
109 {
110 /* Far enough, so disconnect everything */
111 IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
112 }
113
114 /* And fail */
115 return STATUS_INVALID_PARAMETER;
116 }
117
118 /* Now we've used up our First Run */
119 if (FirstRun)
120 {
121 FirstRun = FALSE;
122 }
123 else
124 {
125 /* Move on to the next one */
126 IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt++;
127 }
128 }
129 }
130
131 /* Return Success */
132 return STATUS_SUCCESS;
133 }
134
135 /*
136 * @implemented
137 */
138 VOID
139 NTAPI
140 IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
141 {
142 LONG i;
143 PIO_INTERRUPT IoInterrupt;
144 PAGED_CODE();
145
146 /* Get the I/O Interrupt */
147 IoInterrupt = CONTAINING_RECORD(InterruptObject,
148 IO_INTERRUPT,
149 FirstInterrupt);
150
151 /* Disconnect the first one */
152 KeDisconnectInterrupt(&IoInterrupt->FirstInterrupt);
153
154 /* Now disconnect the others */
155 for (i = 0; i < KeNumberProcessors; i++)
156 {
157 /* Make sure one was registered */
158 if (IoInterrupt->Interrupt[i])
159 {
160 /* Disconnect it */
161 KeDisconnectInterrupt(&InterruptObject[i]);
162 }
163 }
164
165 /* Free the I/O Interrupt */
166 ExFreePool(IoInterrupt);
167 }
168
169 /* EOF */