1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: hal/halx86/mp/mpsirql.c 5 * PURPOSE: Implements IRQLs for multiprocessor systems 6 * PROGRAMMERS: David Welch (welch@cwcom.net) 7 * Casper S. Hornstrup (chorns@users.sourceforge.net) 8 * UPDATE HISTORY: 9 * 12/04/2001 CSH Created 10 */ 11 12 /* INCLUDES *****************************************************************/ 13 14 #include <hal.h> 15 #define NDEBUG 16 #include <debug.h> 17 18 /* GLOBALS ******************************************************************/ 19 20 21 /* FUNCTIONS ****************************************************************/ 22 23 #undef KeGetCurrentIrql 24 KIRQL NTAPI KeGetCurrentIrql (VOID) 25 /* 26 * PURPOSE: Returns the current irq level 27 * RETURNS: The current irq level 28 */ 29 { 30 KIRQL irql; 31 ULONG Flags; 32 33 Flags = __readeflags(); 34 _disable(); 35 36 irql = __readfsbyte(FIELD_OFFSET(KPCR, Irql)); 37 if (irql > HIGH_LEVEL) 38 { 39 DPRINT1 ("CurrentIrql %x\n", irql); 40 ASSERT(FALSE); 41 } 42 if (Flags & EFLAGS_INTERRUPT_MASK) 43 { 44 _enable(); 45 } 46 return irql; 47 } 48 49 50 #undef KeSetCurrentIrql 51 VOID KeSetCurrentIrql (KIRQL NewIrql) 52 /* 53 * PURPOSE: Sets the current irq level without taking any action 54 */ 55 { 56 ULONG Flags; 57 if (NewIrql > HIGH_LEVEL) 58 { 59 DPRINT1 ("NewIrql %x\n", NewIrql); 60 ASSERT(FALSE); 61 } 62 Flags = __readeflags(); 63 _disable(); 64 __writefsbyte(FIELD_OFFSET(KPCR, Irql), NewIrql); 65 if (Flags & EFLAGS_INTERRUPT_MASK) 66 { 67 _enable(); 68 } 69 } 70 71 VOID 72 HalpLowerIrql(KIRQL NewIrql, BOOLEAN FromHalEndSystemInterrupt) 73 { 74 ULONG Flags; 75 UCHAR DpcRequested; 76 if (NewIrql >= DISPATCH_LEVEL) 77 { 78 KeSetCurrentIrql (NewIrql); 79 APICWrite(APIC_TPR, IRQL2TPR (NewIrql) & APIC_TPR_PRI); 80 return; 81 } 82 Flags = __readeflags(); 83 if (KeGetCurrentIrql() > APC_LEVEL) 84 { 85 KeSetCurrentIrql (DISPATCH_LEVEL); 86 APICWrite(APIC_TPR, IRQL2TPR (DISPATCH_LEVEL) & APIC_TPR_PRI); 87 DpcRequested = __readfsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_DPC_REQUEST])); 88 if (FromHalEndSystemInterrupt || DpcRequested) 89 { 90 __writefsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_DPC_REQUEST]), 0); 91 _enable(); 92 KiDispatchInterrupt(); 93 if (!(Flags & EFLAGS_INTERRUPT_MASK)) 94 { 95 _disable(); 96 } 97 } 98 KeSetCurrentIrql (APC_LEVEL); 99 } 100 if (NewIrql == APC_LEVEL) 101 { 102 return; 103 } 104 if (KeGetCurrentThread () != NULL && 105 KeGetCurrentThread ()->ApcState.KernelApcPending) 106 { 107 _enable(); 108 KiDeliverApc(KernelMode, NULL, NULL); 109 if (!(Flags & EFLAGS_INTERRUPT_MASK)) 110 { 111 _disable(); 112 } 113 } 114 KeSetCurrentIrql (PASSIVE_LEVEL); 115 } 116 117 118 /********************************************************************** 119 * NAME EXPORTED 120 * KfLowerIrql 121 * 122 * DESCRIPTION 123 * Restores the irq level on the current processor 124 * 125 * ARGUMENTS 126 * NewIrql = Irql to lower to 127 * 128 * RETURN VALUE 129 * None 130 * 131 * NOTES 132 * Uses fastcall convention 133 */ 134 VOID FASTCALL 135 KfLowerIrql (KIRQL NewIrql) 136 { 137 KIRQL oldIrql = KeGetCurrentIrql(); 138 if (NewIrql > oldIrql) 139 { 140 DPRINT1 ("NewIrql %x CurrentIrql %x\n", NewIrql, oldIrql); 141 ASSERT(FALSE); 142 } 143 HalpLowerIrql (NewIrql, FALSE); 144 } 145 146 147 /********************************************************************** 148 * NAME EXPORTED 149 * KfRaiseIrql 150 * 151 * DESCRIPTION 152 * Raises the hardware priority (irql) 153 * 154 * ARGUMENTS 155 * NewIrql = Irql to raise to 156 * 157 * RETURN VALUE 158 * previous irq level 159 * 160 * NOTES 161 * Uses fastcall convention 162 */ 163 164 KIRQL FASTCALL 165 KfRaiseIrql (KIRQL NewIrql) 166 { 167 KIRQL OldIrql; 168 ULONG Flags; 169 170 Flags = __readeflags(); 171 _disable(); 172 173 OldIrql = KeGetCurrentIrql (); 174 175 if (NewIrql < OldIrql) 176 { 177 DPRINT1 ("CurrentIrql %x NewIrql %x\n", KeGetCurrentIrql (), NewIrql); 178 ASSERT(FALSE); 179 } 180 181 182 if (NewIrql > DISPATCH_LEVEL) 183 { 184 APICWrite (APIC_TPR, IRQL2TPR(NewIrql) & APIC_TPR_PRI); 185 } 186 KeSetCurrentIrql (NewIrql); 187 if (Flags & EFLAGS_INTERRUPT_MASK) 188 { 189 _enable(); 190 } 191 192 return OldIrql; 193 } 194 195 /********************************************************************** 196 * NAME EXPORTED 197 * KeRaiseIrqlToDpcLevel 198 * 199 * DESCRIPTION 200 * Raises the hardware priority (irql) to DISPATCH level 201 * 202 * ARGUMENTS 203 * None 204 * 205 * RETURN VALUE 206 * Previous irq level 207 * 208 * NOTES 209 * Calls KfRaiseIrql 210 */ 211 212 KIRQL NTAPI 213 KeRaiseIrqlToDpcLevel (VOID) 214 { 215 return KfRaiseIrql (DISPATCH_LEVEL); 216 } 217 218 219 /********************************************************************** 220 * NAME EXPORTED 221 * KeRaiseIrqlToSynchLevel 222 * 223 * DESCRIPTION 224 * Raises the hardware priority (irql) to CLOCK2 level 225 * 226 * ARGUMENTS 227 * None 228 * 229 * RETURN VALUE 230 * Previous irq level 231 * 232 * NOTES 233 * Calls KfRaiseIrql 234 */ 235 236 KIRQL NTAPI 237 KeRaiseIrqlToSynchLevel (VOID) 238 { 239 return KfRaiseIrql (CLOCK2_LEVEL); 240 } 241 242 243 BOOLEAN NTAPI 244 HalBeginSystemInterrupt (KIRQL Irql, 245 ULONG Vector, 246 PKIRQL OldIrql) 247 { 248 ULONG Flags; 249 DPRINT("Vector (0x%X) Irql (0x%X)\n", Vector, Irql); 250 251 if (KeGetCurrentIrql () >= Irql) 252 { 253 DPRINT1("current irql %d, new irql %d\n", KeGetCurrentIrql(), Irql); 254 ASSERT(FALSE); 255 } 256 257 Flags = __readeflags(); 258 if (Flags & EFLAGS_INTERRUPT_MASK) 259 { 260 DPRINT1("HalBeginSystemInterrupt was called with interrupt's enabled\n"); 261 ASSERT(FALSE); 262 } 263 APICWrite (APIC_TPR, IRQL2TPR (Irql) & APIC_TPR_PRI); 264 *OldIrql = KeGetCurrentIrql (); 265 KeSetCurrentIrql (Irql); 266 return(TRUE); 267 } 268 269 270 VOID NTAPI 271 HalEndSystemInterrupt (KIRQL Irql, 272 IN PKTRAP_FRAME TrapFrame) 273 /* 274 * FUNCTION: Finish a system interrupt and restore the specified irq level. 275 */ 276 { 277 ULONG Flags; 278 Flags = __readeflags(); 279 280 if (Flags & EFLAGS_INTERRUPT_MASK) 281 { 282 DPRINT1("HalEndSystemInterrupt was called with interrupt's enabled\n"); 283 ASSERT(FALSE); 284 } 285 APICSendEOI(); 286 HalpLowerIrql (Irql, TRUE); 287 } 288 289 VOID 290 NTAPI 291 HalDisableSystemInterrupt(ULONG Vector, 292 KIRQL Irql) 293 { 294 ULONG irq; 295 296 DPRINT ("Vector (0x%X)\n", Vector); 297 298 if (Vector < FIRST_DEVICE_VECTOR || 299 Vector >= FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) 300 { 301 DPRINT1("Not a device interrupt, vector=%x\n", Vector); 302 ASSERT(FALSE); 303 return; 304 } 305 306 irq = VECTOR2IRQ (Vector); 307 IOAPICMaskIrq (irq); 308 309 return; 310 } 311 312 313 BOOLEAN NTAPI 314 HalEnableSystemInterrupt (ULONG Vector, 315 KIRQL Irql, 316 KINTERRUPT_MODE InterruptMode) 317 { 318 ULONG irq; 319 320 if (Vector < FIRST_DEVICE_VECTOR || 321 Vector >= FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) 322 { 323 DPRINT("Not a device interrupt\n"); 324 return FALSE; 325 } 326 327 /* FIXME: We must check if the requested and the assigned interrupt mode is the same */ 328 329 irq = VECTOR2IRQ (Vector); 330 IOAPICUnmaskIrq (irq); 331 332 return TRUE; 333 } 334 335 VOID FASTCALL 336 HalRequestSoftwareInterrupt(IN KIRQL Request) 337 { 338 switch (Request) 339 { 340 case APC_LEVEL: 341 __writefsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_APC_REQUEST]), 1); 342 break; 343 344 case DISPATCH_LEVEL: 345 __writefsbyte(FIELD_OFFSET(KPCR, HalReserved[HAL_DPC_REQUEST]), 1); 346 break; 347 348 default: 349 ASSERT(FALSE); 350 } 351 } 352 353 VOID FASTCALL 354 HalClearSoftwareInterrupt( 355 IN KIRQL Request) 356 { 357 UNIMPLEMENTED; 358 } 359