Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpic.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS HAL 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: hal/halx86/generic/pic.c 00005 * PURPOSE: HAL PIC Management and Control Code 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <hal.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 #ifndef _MINIHAL_ 00018 /* 00019 * This table basically keeps track of level vs edge triggered interrupts. 00020 * Windows has 250+ entries, but it seems stupid to replicate that since the PIC 00021 * can't actually have that many. 00022 * 00023 * When a level interrupt is registered, the respective pointer in this table is 00024 * modified to point to a dimiss routine for level interrupts instead. 00025 * 00026 * The other thing this table does is special case IRQ7, IRQ13 and IRQ15: 00027 * 00028 * - If an IRQ line is deasserted before it is acknowledged due to a noise spike 00029 * generated by an expansion device (since the IRQ line is low during the 1st 00030 * acknowledge bus cycle), the i8259 will keep the line low for at least 100ns 00031 * When the spike passes, a pull-up resistor will return the IRQ line to high. 00032 * Since the PIC requires the input be high until the first acknowledge, the 00033 * i8259 knows that this was a spurious interrupt, and on the second interrupt 00034 * acknowledge cycle, it reports this to the CPU. Since no valid interrupt has 00035 * actually happened Intel hardcoded the chip to report IRQ7 on the master PIC 00036 * and IRQ15 on the slave PIC (IR7 either way). 00037 * 00038 * "ISA System Architecture", 3rd Edition, states that these cases should be 00039 * handled by reading the respective Interrupt Service Request (ISR) bits from 00040 * the affected PIC, and validate whether or not IR7 is set. If it isn't, then 00041 * the interrupt is spurious and should be ignored. 00042 * 00043 * Note that for a spurious IRQ15, we DO have to send an EOI to the master for 00044 * IRQ2 since the line was asserted by the slave when it received the spurious 00045 * IRQ15! 00046 * 00047 * - When the 80287/80387 math co-processor generates an FPU/NPX trap, this is 00048 * connected to IRQ13, so we have to clear the busy latch on the NPX port. 00049 */ 00050 PHAL_DISMISS_INTERRUPT HalpSpecialDismissTable[16] = 00051 { 00052 HalpDismissIrqGeneric, 00053 HalpDismissIrqGeneric, 00054 HalpDismissIrqGeneric, 00055 HalpDismissIrqGeneric, 00056 HalpDismissIrqGeneric, 00057 HalpDismissIrqGeneric, 00058 HalpDismissIrqGeneric, 00059 HalpDismissIrq07, 00060 HalpDismissIrqGeneric, 00061 HalpDismissIrqGeneric, 00062 HalpDismissIrqGeneric, 00063 HalpDismissIrqGeneric, 00064 HalpDismissIrqGeneric, 00065 HalpDismissIrq13, 00066 HalpDismissIrqGeneric, 00067 HalpDismissIrq15 00068 }; 00069 00070 /* 00071 * These are the level IRQ dismissal functions that get copied in the table 00072 * above if the given IRQ is actually level triggered. 00073 */ 00074 PHAL_DISMISS_INTERRUPT HalpSpecialDismissLevelTable[16] = 00075 { 00076 HalpDismissIrqLevel, 00077 HalpDismissIrqLevel, 00078 HalpDismissIrqLevel, 00079 HalpDismissIrqLevel, 00080 HalpDismissIrqLevel, 00081 HalpDismissIrqLevel, 00082 HalpDismissIrqLevel, 00083 HalpDismissIrq07Level, 00084 HalpDismissIrqLevel, 00085 HalpDismissIrqLevel, 00086 HalpDismissIrqLevel, 00087 HalpDismissIrqLevel, 00088 HalpDismissIrqLevel, 00089 HalpDismissIrq13Level, 00090 HalpDismissIrqLevel, 00091 HalpDismissIrq15Level 00092 }; 00093 00094 /* This table contains the static x86 PIC mapping between IRQLs and IRQs */ 00095 ULONG KiI8259MaskTable[32] = 00096 { 00097 #if defined(__GNUC__) && \ 00098 (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) 00099 /* 00100 * It Device IRQLs only start at 4 or higher, so these are just software 00101 * IRQLs that don't really change anything on the hardware 00102 */ 00103 0b00000000000000000000000000000000, /* IRQL 0 */ 00104 0b00000000000000000000000000000000, /* IRQL 1 */ 00105 0b00000000000000000000000000000000, /* IRQL 2 */ 00106 0b00000000000000000000000000000000, /* IRQL 3 */ 00107 00108 /* 00109 * These next IRQLs are actually useless from the PIC perspective, because 00110 * with only 2 PICs, the mask you can send them is only 8 bits each, for 16 00111 * bits total, so these IRQLs are masking off a phantom PIC. 00112 */ 00113 0b11111111100000000000000000000000, /* IRQL 4 */ 00114 0b11111111110000000000000000000000, /* IRQL 5 */ 00115 0b11111111111000000000000000000000, /* IRQL 6 */ 00116 0b11111111111100000000000000000000, /* IRQL 7 */ 00117 0b11111111111110000000000000000000, /* IRQL 8 */ 00118 0b11111111111111000000000000000000, /* IRQL 9 */ 00119 0b11111111111111100000000000000000, /* IRQL 10 */ 00120 0b11111111111111110000000000000000, /* IRQL 11 */ 00121 00122 /* 00123 * Okay, now we're finally starting to mask off IRQs on the slave PIC, from 00124 * IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the 00125 * IRQL sense. 00126 */ 00127 0b11111111111111111000000000000000, /* IRQL 12 */ 00128 0b11111111111111111100000000000000, /* IRQL 13 */ 00129 0b11111111111111111110000000000000, /* IRQL 14 */ 00130 0b11111111111111111111000000000000, /* IRQL 15 */ 00131 0b11111111111111111111100000000000, /* IRQL 16 */ 00132 0b11111111111111111111110000000000, /* IRQL 17 */ 00133 0b11111111111111111111111000000000, /* IRQL 18 */ 00134 0b11111111111111111111111000000000, /* IRQL 19 */ 00135 00136 /* 00137 * Now we mask off the IRQs on the master. Notice the 0 "droplet"? You might 00138 * have also seen that IRQL 18 and 19 are essentially equal as far as the 00139 * PIC is concerned. That bit is actually IRQ8, which happens to be the RTC. 00140 * The RTC will keep firing as long as we don't reach PROFILE_LEVEL which 00141 * actually kills it. The RTC clock (unlike the system clock) is used by the 00142 * profiling APIs in the HAL, so that explains the logic. 00143 */ 00144 0b11111111111111111111111010000000, /* IRQL 20 */ 00145 0b11111111111111111111111011000000, /* IRQL 21 */ 00146 0b11111111111111111111111011100000, /* IRQL 22 */ 00147 0b11111111111111111111111011110000, /* IRQL 23 */ 00148 0b11111111111111111111111011111000, /* IRQL 24 */ 00149 0b11111111111111111111111011111000, /* IRQL 25 */ 00150 0b11111111111111111111111011111010, /* IRQL 26 */ 00151 0b11111111111111111111111111111010, /* IRQL 27 */ 00152 00153 /* 00154 * IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last 00155 * IRQL to modify a bit on the master PIC. It happens to modify the very 00156 * last of the IRQs, IRQ0, which corresponds to the system clock interval 00157 * timer that keeps track of time (the Windows heartbeat). We only want to 00158 * turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the 00159 * same to give this guy a chance to come up higher. Note that IRQL 28 is 00160 * called CLOCK2_LEVEL, which explains the usage we just explained. 00161 */ 00162 0b11111111111111111111111111111011, /* IRQL 28 */ 00163 00164 /* 00165 * We have finished off with the PIC so there's nothing left to mask at the 00166 * level of these IRQLs, making them only logical IRQLs on x86 machines. 00167 * Note that we have another 0 "droplet" you might've caught since IRQL 26. 00168 * In this case, it's the 2nd bit that never gets turned off, which is IRQ2, 00169 * the cascade IRQ that we use to bridge the slave PIC with the master PIC. 00170 * We never want to turn it off, so no matter the IRQL, it will be set to 0. 00171 */ 00172 0b11111111111111111111111111111011, /* IRQL 29 */ 00173 0b11111111111111111111111111111011, /* IRQL 30 */ 00174 0b11111111111111111111111111111011 /* IRQL 31 */ 00175 #else 00176 0, /* IRQL 0 */ 00177 0, /* IRQL 1 */ 00178 0, /* IRQL 2 */ 00179 0, /* IRQL 3 */ 00180 0xFF800000, /* IRQL 4 */ 00181 0xFFC00000, /* IRQL 5 */ 00182 0xFFE00000, /* IRQL 6 */ 00183 0xFFF00000, /* IRQL 7 */ 00184 0xFFF80000, /* IRQL 8 */ 00185 0xFFFC0000, /* IRQL 9 */ 00186 0xFFFE0000, /* IRQL 10 */ 00187 0xFFFF0000, /* IRQL 11 */ 00188 0xFFFF8000, /* IRQL 12 */ 00189 0xFFFFC000, /* IRQL 13 */ 00190 0xFFFFE000, /* IRQL 14 */ 00191 0xFFFFF000, /* IRQL 15 */ 00192 0xFFFFF800, /* IRQL 16 */ 00193 0xFFFFFC00, /* IRQL 17 */ 00194 0xFFFFFE00, /* IRQL 18 */ 00195 0xFFFFFE00, /* IRQL 19 */ 00196 0xFFFFFE80, /* IRQL 20 */ 00197 0xFFFFFEC0, /* IRQL 21 */ 00198 0xFFFFFEE0, /* IRQL 22 */ 00199 0xFFFFFEF0, /* IRQL 23 */ 00200 0xFFFFFEF8, /* IRQL 24 */ 00201 0xFFFFFEF8, /* IRQL 25 */ 00202 0xFFFFFEFA, /* IRQL 26 */ 00203 0xFFFFFFFA, /* IRQL 27 */ 00204 0xFFFFFFFB, /* IRQL 28 */ 00205 0xFFFFFFFB, /* IRQL 29 */ 00206 0xFFFFFFFB, /* IRQL 30 */ 00207 0xFFFFFFFB /* IRQL 31 */ 00208 #endif 00209 }; 00210 00211 /* This table indicates which IRQs, if pending, can preempt a given IRQL level */ 00212 ULONG FindHigherIrqlMask[32] = 00213 { 00214 #if defined(__GNUC__) && \ 00215 (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) 00216 /* 00217 * Software IRQLs, at these levels all hardware interrupts can preempt. 00218 * Each higher IRQL simply enables which software IRQL can preempt the 00219 * current level. 00220 */ 00221 0b11111111111111111111111111111110, /* IRQL 0 */ 00222 0b11111111111111111111111111111100, /* IRQL 1 */ 00223 0b11111111111111111111111111111000, /* IRQL 2 */ 00224 00225 /* 00226 * IRQL3 means only hardware IRQLs can now preempt. These last 4 zeros will 00227 * then continue throughout the rest of the list, trickling down. 00228 */ 00229 0b11111111111111111111111111110000, /* IRQL 3 */ 00230 00231 /* 00232 * Just like in the previous list, these masks don't really mean anything 00233 * since we've only got two PICs with 16 possible IRQs total 00234 */ 00235 0b00000111111111111111111111110000, /* IRQL 4 */ 00236 0b00000011111111111111111111110000, /* IRQL 5 */ 00237 0b00000001111111111111111111110000, /* IRQL 6 */ 00238 0b00000000111111111111111111110000, /* IRQL 7 */ 00239 0b00000000011111111111111111110000, /* IRQL 8 */ 00240 0b00000000001111111111111111110000, /* IRQL 9 */ 00241 0b00000000000111111111111111110000, /* IRQL 10 */ 00242 00243 /* 00244 * Now we start progressivly limiting which slave PIC interrupts have the 00245 * right to preempt us at each level. 00246 */ 00247 0b00000000000011111111111111110000, /* IRQL 11 */ 00248 0b00000000000001111111111111110000, /* IRQL 12 */ 00249 0b00000000000000111111111111110000, /* IRQL 13 */ 00250 0b00000000000000011111111111110000, /* IRQL 14 */ 00251 0b00000000000000001111111111110000, /* IRQL 15 */ 00252 0b00000000000000000111111111110000, /* IRQL 16 */ 00253 0b00000000000000000011111111110000, /* IRQL 17 */ 00254 0b00000000000000000001111111110000, /* IRQL 18 */ 00255 0b00000000000000000001111111110000, /* IRQL 19 */ 00256 00257 /* 00258 * Also recall from the earlier table that IRQL 18/19 are treated the same 00259 * in order to spread the masks better thoughout the 32 IRQLs and to reflect 00260 * the fact that some bits will always stay on until much higher IRQLs since 00261 * they are system-critical. One such example is the 1 bit that you start to 00262 * see trickling down here. This is IRQ8, the RTC timer used for profiling, 00263 * so it will always preempt until we reach PROFILE_LEVEL. 00264 */ 00265 0b00000000000000000001011111110000, /* IRQL 20 */ 00266 0b00000000000000000001001111110000, /* IRQL 20 */ 00267 0b00000000000000000001000111110000, /* IRQL 22 */ 00268 0b00000000000000000001000011110000, /* IRQL 23 */ 00269 0b00000000000000000001000001110000, /* IRQL 24 */ 00270 0b00000000000000000001000000110000, /* IRQL 25 */ 00271 0b00000000000000000001000000010000, /* IRQL 26 */ 00272 00273 /* At this point, only the clock (IRQ0) can still preempt... */ 00274 0b00000000000000000000000000010000, /* IRQL 27 */ 00275 00276 /* And any higher than that there's no relation with hardware PICs anymore */ 00277 0b00000000000000000000000000000000, /* IRQL 28 */ 00278 0b00000000000000000000000000000000, /* IRQL 29 */ 00279 0b00000000000000000000000000000000, /* IRQL 30 */ 00280 0b00000000000000000000000000000000 /* IRQL 31 */ 00281 #else 00282 0xFFFFFFFE, /* IRQL 0 */ 00283 0xFFFFFFFC, /* IRQL 1 */ 00284 0xFFFFFFF8, /* IRQL 2 */ 00285 0xFFFFFFF0, /* IRQL 3 */ 00286 0x7FFFFF0, /* IRQL 4 */ 00287 0x3FFFFF0, /* IRQL 5 */ 00288 0x1FFFFF0, /* IRQL 6 */ 00289 0x0FFFFF0, /* IRQL 7 */ 00290 0x7FFFF0, /* IRQL 8 */ 00291 0x3FFFF0, /* IRQL 9 */ 00292 0x1FFFF0, /* IRQL 10 */ 00293 0x0FFFF0, /* IRQL 11 */ 00294 0x7FFF0, /* IRQL 12 */ 00295 0x3FFF0, /* IRQL 13 */ 00296 0x1FFF0, /* IRQL 14 */ 00297 0x0FFF0, /* IRQL 15 */ 00298 0x7FF0, /* IRQL 16 */ 00299 0x3FF0, /* IRQL 17 */ 00300 0x1FF0, /* IRQL 18 */ 00301 0x1FF0, /* IRQL 19 */ 00302 0x17F0, /* IRQL 20 */ 00303 0x13F0, /* IRQL 21 */ 00304 0x11F0, /* IRQL 22 */ 00305 0x10F0, /* IRQL 23 */ 00306 0x1070, /* IRQL 24 */ 00307 0x1030, /* IRQL 25 */ 00308 0x1010, /* IRQL 26 */ 00309 0x10, /* IRQL 27 */ 00310 0, /* IRQL 28 */ 00311 0, /* IRQL 29 */ 00312 0, /* IRQL 30 */ 00313 0 /* IRQL 31 */ 00314 #endif 00315 }; 00316 00317 /* Denotes minimum required IRQL before we can process pending SW interrupts */ 00318 KIRQL SWInterruptLookUpTable[8] = 00319 { 00320 PASSIVE_LEVEL, /* IRR 0 */ 00321 PASSIVE_LEVEL, /* IRR 1 */ 00322 APC_LEVEL, /* IRR 2 */ 00323 APC_LEVEL, /* IRR 3 */ 00324 DISPATCH_LEVEL, /* IRR 4 */ 00325 DISPATCH_LEVEL, /* IRR 5 */ 00326 DISPATCH_LEVEL, /* IRR 6 */ 00327 DISPATCH_LEVEL /* IRR 7 */ 00328 }; 00329 00330 #if defined(__GNUC__) 00331 00332 #define HalpDelayedHardwareInterrupt(x) \ 00333 VOID HalpHardwareInterrupt##x(VOID); \ 00334 VOID \ 00335 HalpHardwareInterrupt##x(VOID) \ 00336 { \ 00337 asm volatile ("int $%c0\n"::"i"(PRIMARY_VECTOR_BASE + x)); \ 00338 } 00339 00340 #elif defined(_MSC_VER) 00341 00342 #define HalpDelayedHardwareInterrupt(x) \ 00343 VOID HalpHardwareInterrupt##x(VOID); \ 00344 VOID \ 00345 HalpHardwareInterrupt##x(VOID) \ 00346 { \ 00347 __asm \ 00348 { \ 00349 int PRIMARY_VECTOR_BASE + x \ 00350 } \ 00351 } 00352 00353 #else 00354 #error Unsupported compiler 00355 #endif 00356 00357 /* Pending/delayed hardware interrupt handlers */ 00358 HalpDelayedHardwareInterrupt(0); 00359 HalpDelayedHardwareInterrupt(1); 00360 HalpDelayedHardwareInterrupt(2); 00361 HalpDelayedHardwareInterrupt(3); 00362 HalpDelayedHardwareInterrupt(4); 00363 HalpDelayedHardwareInterrupt(5); 00364 HalpDelayedHardwareInterrupt(6); 00365 HalpDelayedHardwareInterrupt(7); 00366 HalpDelayedHardwareInterrupt(8); 00367 HalpDelayedHardwareInterrupt(9); 00368 HalpDelayedHardwareInterrupt(10); 00369 HalpDelayedHardwareInterrupt(11); 00370 HalpDelayedHardwareInterrupt(12); 00371 HalpDelayedHardwareInterrupt(13); 00372 HalpDelayedHardwareInterrupt(14); 00373 HalpDelayedHardwareInterrupt(15); 00374 00375 /* Handlers for pending interrupts */ 00376 PHAL_SW_INTERRUPT_HANDLER SWInterruptHandlerTable[20] = 00377 { 00378 KiUnexpectedInterrupt, 00379 HalpApcInterrupt, 00380 HalpDispatchInterrupt2, 00381 KiUnexpectedInterrupt, 00382 HalpHardwareInterrupt0, 00383 HalpHardwareInterrupt1, 00384 HalpHardwareInterrupt2, 00385 HalpHardwareInterrupt3, 00386 HalpHardwareInterrupt4, 00387 HalpHardwareInterrupt5, 00388 HalpHardwareInterrupt6, 00389 HalpHardwareInterrupt7, 00390 HalpHardwareInterrupt8, 00391 HalpHardwareInterrupt9, 00392 HalpHardwareInterrupt10, 00393 HalpHardwareInterrupt11, 00394 HalpHardwareInterrupt12, 00395 HalpHardwareInterrupt13, 00396 HalpHardwareInterrupt14, 00397 HalpHardwareInterrupt15 00398 }; 00399 00400 /* Handlers for pending software interrupts when we already have a trap frame*/ 00401 PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3] = 00402 { 00403 (PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)KiUnexpectedInterrupt, 00404 HalpApcInterrupt2ndEntry, 00405 HalpDispatchInterrupt2ndEntry 00406 }; 00407 00408 LONG HalpEisaELCR; 00409 00410 /* FUNCTIONS ******************************************************************/ 00411 00412 VOID 00413 NTAPI 00414 HalpInitializePICs(IN BOOLEAN EnableInterrupts) 00415 { 00416 ULONG EFlags; 00417 I8259_ICW1 Icw1; 00418 I8259_ICW2 Icw2; 00419 I8259_ICW3 Icw3; 00420 I8259_ICW4 Icw4; 00421 EISA_ELCR Elcr; 00422 ULONG i, j; 00423 00424 /* Save EFlags and disable interrupts */ 00425 EFlags = __readeflags(); 00426 _disable(); 00427 00428 /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ 00429 Icw1.NeedIcw4 = TRUE; 00430 Icw1.InterruptMode = EdgeTriggered; 00431 Icw1.OperatingMode = Cascade; 00432 Icw1.Interval = Interval8; 00433 Icw1.Init = TRUE; 00434 Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ 00435 __outbyte(PIC1_CONTROL_PORT, Icw1.Bits); 00436 00437 /* Set interrupt vector base */ 00438 Icw2.Bits = PRIMARY_VECTOR_BASE; 00439 __outbyte(PIC1_DATA_PORT, Icw2.Bits); 00440 00441 /* Connect slave to IRQ 2 */ 00442 Icw3.Bits = 0; 00443 Icw3.SlaveIrq2 = TRUE; 00444 __outbyte(PIC1_DATA_PORT, Icw3.Bits); 00445 00446 /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ 00447 Icw4.Reserved = 0; 00448 Icw4.SystemMode = New8086Mode; 00449 Icw4.EoiMode = NormalEoi; 00450 Icw4.BufferedMode = NonBuffered; 00451 Icw4.SpecialFullyNestedMode = FALSE; 00452 __outbyte(PIC1_DATA_PORT, Icw4.Bits); 00453 00454 /* Mask all interrupts */ 00455 __outbyte(PIC1_DATA_PORT, 0xFF); 00456 00457 /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ 00458 Icw1.NeedIcw4 = TRUE; 00459 Icw1.InterruptMode = EdgeTriggered; 00460 Icw1.OperatingMode = Cascade; 00461 Icw1.Interval = Interval8; 00462 Icw1.Init = TRUE; 00463 Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ 00464 __outbyte(PIC2_CONTROL_PORT, Icw1.Bits); 00465 00466 /* Set interrupt vector base */ 00467 Icw2.Bits = PRIMARY_VECTOR_BASE + 8; 00468 __outbyte(PIC2_DATA_PORT, Icw2.Bits); 00469 00470 /* Slave ID */ 00471 Icw3.Bits = 0; 00472 Icw3.SlaveId = 2; 00473 __outbyte(PIC2_DATA_PORT, Icw3.Bits); 00474 00475 /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ 00476 Icw4.Reserved = 0; 00477 Icw4.SystemMode = New8086Mode; 00478 Icw4.EoiMode = NormalEoi; 00479 Icw4.BufferedMode = NonBuffered; 00480 Icw4.SpecialFullyNestedMode = FALSE; 00481 __outbyte(PIC2_DATA_PORT, Icw4.Bits); 00482 00483 /* Mask all interrupts */ 00484 __outbyte(PIC2_DATA_PORT, 0xFF); 00485 00486 /* Read EISA Edge/Level Register for master and slave */ 00487 Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER); 00488 00489 /* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */ 00490 if (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) && 00491 !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level)) 00492 { 00493 /* ELCR is as it's supposed to be, save it */ 00494 HalpEisaELCR = Elcr.Bits; 00495 00496 /* Scan for level interrupts */ 00497 for (i = 1, j = 0; j < 16; i <<= 1, j++) 00498 { 00499 if (HalpEisaELCR & i) 00500 { 00501 /* Switch handler to level */ 00502 SWInterruptHandlerTable[j + 4] = HalpHardwareInterruptLevel; 00503 00504 /* Switch dismiss to level */ 00505 HalpSpecialDismissTable[j] = HalpSpecialDismissLevelTable[j]; 00506 } 00507 } 00508 } 00509 00510 /* Register IRQ 2 */ 00511 HalpRegisterVector(IDT_INTERNAL, 00512 PRIMARY_VECTOR_BASE + 2, 00513 PRIMARY_VECTOR_BASE + 2, 00514 HIGH_LEVEL); 00515 00516 /* Restore interrupt state */ 00517 if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; 00518 __writeeflags(EFlags); 00519 } 00520 00521 UCHAR 00522 FASTCALL 00523 HalpIrqToVector(UCHAR Irq) 00524 { 00525 return (PRIMARY_VECTOR_BASE + Irq); 00526 } 00527 00528 UCHAR 00529 FASTCALL 00530 HalpVectorToIrq(UCHAR Vector) 00531 { 00532 return (Vector - PRIMARY_VECTOR_BASE); 00533 } 00534 00535 KIRQL 00536 FASTCALL 00537 HalpVectorToIrql(UCHAR Vector) 00538 { 00539 return (PROFILE_LEVEL - (Vector - PRIMARY_VECTOR_BASE)); 00540 } 00541 00542 /* IRQL MANAGEMENT ************************************************************/ 00543 00544 /* 00545 * @implemented 00546 */ 00547 KIRQL 00548 NTAPI 00549 KeGetCurrentIrql(VOID) 00550 { 00551 /* Return the IRQL */ 00552 return KeGetPcr()->Irql; 00553 } 00554 00555 /* 00556 * @implemented 00557 */ 00558 KIRQL 00559 NTAPI 00560 KeRaiseIrqlToDpcLevel(VOID) 00561 { 00562 PKPCR Pcr = KeGetPcr(); 00563 KIRQL CurrentIrql; 00564 00565 /* Save and update IRQL */ 00566 CurrentIrql = Pcr->Irql; 00567 Pcr->Irql = DISPATCH_LEVEL; 00568 00569 #if DBG 00570 /* Validate correct raise */ 00571 if (CurrentIrql > DISPATCH_LEVEL) KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL); 00572 #endif 00573 00574 /* Return the previous value */ 00575 return CurrentIrql; 00576 } 00577 00578 /* 00579 * @implemented 00580 */ 00581 KIRQL 00582 NTAPI 00583 KeRaiseIrqlToSynchLevel(VOID) 00584 { 00585 PKPCR Pcr = KeGetPcr(); 00586 KIRQL CurrentIrql; 00587 00588 /* Save and update IRQL */ 00589 CurrentIrql = Pcr->Irql; 00590 Pcr->Irql = SYNCH_LEVEL; 00591 00592 #if DBG 00593 /* Validate correct raise */ 00594 if (CurrentIrql > SYNCH_LEVEL) 00595 { 00596 /* Crash system */ 00597 KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, 00598 CurrentIrql, 00599 SYNCH_LEVEL, 00600 0, 00601 1); 00602 } 00603 #endif 00604 00605 /* Return the previous value */ 00606 return CurrentIrql; 00607 } 00608 00609 /* 00610 * @implemented 00611 */ 00612 KIRQL 00613 FASTCALL 00614 KfRaiseIrql(IN KIRQL NewIrql) 00615 { 00616 PKPCR Pcr = KeGetPcr(); 00617 KIRQL CurrentIrql; 00618 00619 /* Read current IRQL */ 00620 CurrentIrql = Pcr->Irql; 00621 00622 #if DBG 00623 /* Validate correct raise */ 00624 if (CurrentIrql > NewIrql) 00625 { 00626 /* Crash system */ 00627 Pcr->Irql = PASSIVE_LEVEL; 00628 KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL); 00629 } 00630 #endif 00631 00632 /* Set new IRQL */ 00633 Pcr->Irql = NewIrql; 00634 00635 /* Return old IRQL */ 00636 return CurrentIrql; 00637 } 00638 00639 00640 /* 00641 * @implemented 00642 */ 00643 VOID 00644 FASTCALL 00645 KfLowerIrql(IN KIRQL OldIrql) 00646 { 00647 ULONG EFlags; 00648 ULONG PendingIrql, PendingIrqlMask; 00649 PKPCR Pcr = KeGetPcr(); 00650 PIC_MASK Mask; 00651 00652 #if DBG 00653 /* Validate correct lower */ 00654 if (OldIrql > Pcr->Irql) 00655 { 00656 /* Crash system */ 00657 Pcr->Irql = HIGH_LEVEL; 00658 KeBugCheck(IRQL_NOT_LESS_OR_EQUAL); 00659 } 00660 #endif 00661 00662 /* Save EFlags and disable interrupts */ 00663 EFlags = __readeflags(); 00664 _disable(); 00665 00666 /* Set old IRQL */ 00667 Pcr->Irql = OldIrql; 00668 00669 /* Check for pending software interrupts and compare with current IRQL */ 00670 PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; 00671 if (PendingIrqlMask) 00672 { 00673 /* Check if pending IRQL affects hardware state */ 00674 BitScanReverse(&PendingIrql, PendingIrqlMask); 00675 if (PendingIrql > DISPATCH_LEVEL) 00676 { 00677 /* Set new PIC mask */ 00678 Mask.Both = Pcr->IDR & 0xFFFF; 00679 __outbyte(PIC1_DATA_PORT, Mask.Master); 00680 __outbyte(PIC2_DATA_PORT, Mask.Slave); 00681 00682 /* Clear IRR bit */ 00683 Pcr->IRR ^= (1 << PendingIrql); 00684 } 00685 00686 /* Now handle pending interrupt */ 00687 SWInterruptHandlerTable[PendingIrql](); 00688 } 00689 00690 /* Restore interrupt state */ 00691 __writeeflags(EFlags); 00692 } 00693 00694 /* SOFTWARE INTERRUPTS ********************************************************/ 00695 00696 /* 00697 * @implemented 00698 */ 00699 VOID 00700 FASTCALL 00701 HalRequestSoftwareInterrupt(IN KIRQL Irql) 00702 { 00703 ULONG EFlags; 00704 PKPCR Pcr = KeGetPcr(); 00705 KIRQL PendingIrql; 00706 00707 /* Save EFlags and disable interrupts */ 00708 EFlags = __readeflags(); 00709 _disable(); 00710 00711 /* Mask out the requested bit */ 00712 Pcr->IRR |= (1 << Irql); 00713 00714 /* Check for pending software interrupts and compare with current IRQL */ 00715 PendingIrql = SWInterruptLookUpTable[Pcr->IRR & 3]; 00716 if (PendingIrql > Pcr->Irql) SWInterruptHandlerTable[PendingIrql](); 00717 00718 /* Restore interrupt state */ 00719 __writeeflags(EFlags); 00720 } 00721 00722 /* 00723 * @implemented 00724 */ 00725 VOID 00726 FASTCALL 00727 HalClearSoftwareInterrupt(IN KIRQL Irql) 00728 { 00729 /* Mask out the requested bit */ 00730 KeGetPcr()->IRR &= ~(1 << Irql); 00731 } 00732 00733 VOID 00734 NTAPI 00735 HalpEndSoftwareInterrupt(IN KIRQL OldIrql, 00736 IN PKTRAP_FRAME TrapFrame) 00737 { 00738 ULONG PendingIrql, PendingIrqlMask, PendingIrqMask; 00739 PKPCR Pcr = KeGetPcr(); 00740 PIC_MASK Mask; 00741 00742 /* Set old IRQL */ 00743 Pcr->Irql = OldIrql; 00744 00745 /* Loop checking for pending interrupts */ 00746 while (TRUE) 00747 { 00748 /* Check for pending software interrupts and compare with current IRQL */ 00749 PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; 00750 if (!PendingIrqlMask) return; 00751 00752 /* Check for in-service delayed interrupt */ 00753 if (Pcr->IrrActive & 0xFFFFFFF0) return; 00754 00755 /* Check if pending IRQL affects hardware state */ 00756 BitScanReverse(&PendingIrql, PendingIrqlMask); 00757 if (PendingIrql > DISPATCH_LEVEL) 00758 { 00759 /* Set new PIC mask */ 00760 Mask.Both = Pcr->IDR & 0xFFFF; 00761 __outbyte(PIC1_DATA_PORT, Mask.Master); 00762 __outbyte(PIC2_DATA_PORT, Mask.Slave); 00763 00764 /* Set active bit otherwise, and clear it from IRR */ 00765 PendingIrqMask = (1 << PendingIrql); 00766 Pcr->IrrActive |= PendingIrqMask; 00767 Pcr->IRR ^= PendingIrqMask; 00768 00769 /* Handle delayed hardware interrupt */ 00770 SWInterruptHandlerTable[PendingIrql](); 00771 00772 /* Handling complete */ 00773 Pcr->IrrActive ^= PendingIrqMask; 00774 } 00775 else 00776 { 00777 /* No need to loop checking for hardware interrupts */ 00778 SWInterruptHandlerTable2[PendingIrql](TrapFrame); 00779 } 00780 } 00781 } 00782 00783 /* EDGE INTERRUPT DISMISSAL FUNCTIONS *****************************************/ 00784 00785 BOOLEAN 00786 FORCEINLINE 00787 _HalpDismissIrqGeneric(IN KIRQL Irql, 00788 IN ULONG Irq, 00789 OUT PKIRQL OldIrql) 00790 { 00791 PIC_MASK Mask; 00792 KIRQL CurrentIrql; 00793 I8259_OCW2 Ocw2; 00794 PKPCR Pcr = KeGetPcr(); 00795 00796 /* First save current IRQL and compare it to the requested one */ 00797 CurrentIrql = Pcr->Irql; 00798 00799 /* Check if this interrupt is really allowed to happen */ 00800 if (Irql > CurrentIrql) 00801 { 00802 /* Set the new IRQL and return the current one */ 00803 Pcr->Irql = Irql; 00804 *OldIrql = CurrentIrql; 00805 00806 /* Prepare OCW2 for EOI */ 00807 Ocw2.Bits = 0; 00808 Ocw2.EoiMode = SpecificEoi; 00809 00810 /* Check which PIC needs the EOI */ 00811 if (Irq > 8) 00812 { 00813 /* Send the EOI for the IRQ */ 00814 __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF)); 00815 00816 /* Send the EOI for IRQ2 on the master because this was cascaded */ 00817 __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); 00818 } 00819 else 00820 { 00821 /* Send the EOI for the IRQ */ 00822 __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq &0xFF)); 00823 } 00824 00825 /* Enable interrupts and return success */ 00826 _enable(); 00827 return TRUE; 00828 } 00829 00830 /* Update the IRR so that we deliver this interrupt when the IRQL is proper */ 00831 Pcr->IRR |= (1 << (Irq + 4)); 00832 00833 /* Set new PIC mask to real IRQL level, since the optimization is lost now */ 00834 Mask.Both = (KiI8259MaskTable[CurrentIrql] | Pcr->IDR) & 0xFFFF; 00835 __outbyte(PIC1_DATA_PORT, Mask.Master); 00836 __outbyte(PIC2_DATA_PORT, Mask.Slave); 00837 00838 /* Now lie and say this was spurious */ 00839 return FALSE; 00840 } 00841 00842 BOOLEAN 00843 REGISTERCALL 00844 HalpDismissIrqGeneric(IN KIRQL Irql, 00845 IN ULONG Irq, 00846 OUT PKIRQL OldIrql) 00847 { 00848 /* Run the inline code */ 00849 return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); 00850 } 00851 00852 BOOLEAN 00853 REGISTERCALL 00854 HalpDismissIrq15(IN KIRQL Irql, 00855 IN ULONG Irq, 00856 OUT PKIRQL OldIrql) 00857 { 00858 I8259_OCW3 Ocw3; 00859 I8259_OCW2 Ocw2; 00860 I8259_ISR Isr; 00861 00862 /* Request the ISR */ 00863 Ocw3.Bits = 0; 00864 Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */ 00865 Ocw3.ReadRequest = ReadIsr; 00866 __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits); 00867 00868 /* Read the ISR */ 00869 Isr.Bits = __inbyte(PIC2_CONTROL_PORT); 00870 00871 /* Is IRQ15 really active (this is IR7) */ 00872 if (Isr.Irq7 == FALSE) 00873 { 00874 /* It isn't, so we have to EOI IRQ2 because this was cascaded */ 00875 Ocw2.Bits = 0; 00876 Ocw2.EoiMode = SpecificEoi; 00877 __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); 00878 00879 /* And now fail since this was spurious */ 00880 return FALSE; 00881 } 00882 00883 /* Do normal interrupt dismiss */ 00884 return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); 00885 } 00886 00887 00888 BOOLEAN 00889 REGISTERCALL 00890 HalpDismissIrq13(IN KIRQL Irql, 00891 IN ULONG Irq, 00892 OUT PKIRQL OldIrql) 00893 { 00894 /* Clear the FPU busy latch */ 00895 __outbyte(0xF0, 0); 00896 00897 /* Do normal interrupt dismiss */ 00898 return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); 00899 } 00900 00901 BOOLEAN 00902 REGISTERCALL 00903 HalpDismissIrq07(IN KIRQL Irql, 00904 IN ULONG Irq, 00905 OUT PKIRQL OldIrql) 00906 { 00907 I8259_OCW3 Ocw3; 00908 I8259_ISR Isr; 00909 00910 /* Request the ISR */ 00911 Ocw3.Bits = 0; 00912 Ocw3.Sbo = 1; 00913 Ocw3.ReadRequest = ReadIsr; 00914 __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits); 00915 00916 /* Read the ISR */ 00917 Isr.Bits = __inbyte(PIC1_CONTROL_PORT); 00918 00919 /* Is IRQ 7 really active? If it isn't, this is spurious so fail */ 00920 if (Isr.Irq7 == FALSE) return FALSE; 00921 00922 /* Do normal interrupt dismiss */ 00923 return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); 00924 } 00925 00926 /* LEVEL INTERRUPT DISMISSAL FUNCTIONS ****************************************/ 00927 00928 BOOLEAN 00929 FORCEINLINE 00930 _HalpDismissIrqLevel(IN KIRQL Irql, 00931 IN ULONG Irq, 00932 OUT PKIRQL OldIrql) 00933 { 00934 PIC_MASK Mask; 00935 KIRQL CurrentIrql; 00936 I8259_OCW2 Ocw2; 00937 PKPCR Pcr = KeGetPcr(); 00938 00939 /* Update the PIC */ 00940 Mask.Both = (KiI8259MaskTable[Irql] | Pcr->IDR) & 0xFFFF; 00941 __outbyte(PIC1_DATA_PORT, Mask.Master); 00942 __outbyte(PIC2_DATA_PORT, Mask.Slave); 00943 00944 /* Update the IRR so that we clear this interrupt when the IRQL is proper */ 00945 Pcr->IRR |= (1 << (Irq + 4)); 00946 00947 /* Save current IRQL */ 00948 CurrentIrql = Pcr->Irql; 00949 00950 /* Prepare OCW2 for EOI */ 00951 Ocw2.Bits = 0; 00952 Ocw2.EoiMode = SpecificEoi; 00953 00954 /* Check which PIC needs the EOI */ 00955 if (Irq > 8) 00956 { 00957 /* Send the EOI for the IRQ */ 00958 __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | ((Irq - 8) & 0xFF)); 00959 00960 /* Send the EOI for IRQ2 on the master because this was cascaded */ 00961 __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); 00962 } 00963 else 00964 { 00965 /* Send the EOI for the IRQ */ 00966 __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | (Irq & 0xFF)); 00967 } 00968 00969 /* Check if this interrupt should be allowed to happen */ 00970 if (Irql > CurrentIrql) 00971 { 00972 /* Set the new IRQL and return the current one */ 00973 Pcr->Irql = Irql; 00974 *OldIrql = CurrentIrql; 00975 00976 /* Enable interrupts and return success */ 00977 _enable(); 00978 return TRUE; 00979 } 00980 00981 /* Now lie and say this was spurious */ 00982 return FALSE; 00983 } 00984 00985 BOOLEAN 00986 REGISTERCALL 00987 HalpDismissIrqLevel(IN KIRQL Irql, 00988 IN ULONG Irq, 00989 OUT PKIRQL OldIrql) 00990 { 00991 /* Run the inline code */ 00992 return _HalpDismissIrqLevel(Irql, Irq, OldIrql); 00993 } 00994 00995 BOOLEAN 00996 REGISTERCALL 00997 HalpDismissIrq15Level(IN KIRQL Irql, 00998 IN ULONG Irq, 00999 OUT PKIRQL OldIrql) 01000 { 01001 I8259_OCW3 Ocw3; 01002 I8259_OCW2 Ocw2; 01003 I8259_ISR Isr; 01004 01005 /* Request the ISR */ 01006 Ocw3.Bits = 0; 01007 Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */ 01008 Ocw3.ReadRequest = ReadIsr; 01009 __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits); 01010 01011 /* Read the ISR */ 01012 Isr.Bits = __inbyte(PIC2_CONTROL_PORT); 01013 01014 /* Is IRQ15 really active (this is IR7) */ 01015 if (Isr.Irq7 == FALSE) 01016 { 01017 /* It isn't, so we have to EOI IRQ2 because this was cascaded */ 01018 Ocw2.Bits = 0; 01019 Ocw2.EoiMode = SpecificEoi; 01020 __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); 01021 01022 /* And now fail since this was spurious */ 01023 return FALSE; 01024 } 01025 01026 /* Do normal interrupt dismiss */ 01027 return _HalpDismissIrqLevel(Irql, Irq, OldIrql); 01028 } 01029 01030 BOOLEAN 01031 REGISTERCALL 01032 HalpDismissIrq13Level(IN KIRQL Irql, 01033 IN ULONG Irq, 01034 OUT PKIRQL OldIrql) 01035 { 01036 /* Clear the FPU busy latch */ 01037 __outbyte(0xF0, 0); 01038 01039 /* Do normal interrupt dismiss */ 01040 return _HalpDismissIrqLevel(Irql, Irq, OldIrql); 01041 } 01042 01043 BOOLEAN 01044 REGISTERCALL 01045 HalpDismissIrq07Level(IN KIRQL Irql, 01046 IN ULONG Irq, 01047 OUT PKIRQL OldIrql) 01048 { 01049 I8259_OCW3 Ocw3; 01050 I8259_ISR Isr; 01051 01052 /* Request the ISR */ 01053 Ocw3.Bits = 0; 01054 Ocw3.Sbo = 1; 01055 Ocw3.ReadRequest = ReadIsr; 01056 __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits); 01057 01058 /* Read the ISR */ 01059 Isr.Bits = __inbyte(PIC1_CONTROL_PORT); 01060 01061 /* Is IRQ 7 really active? If it isn't, this is spurious so fail */ 01062 if (Isr.Irq7 == FALSE) return FALSE; 01063 01064 /* Do normal interrupt dismiss */ 01065 return _HalpDismissIrqLevel(Irql, Irq, OldIrql); 01066 } 01067 01068 VOID 01069 HalpHardwareInterruptLevel(VOID) 01070 { 01071 PKPCR Pcr = KeGetPcr(); 01072 ULONG PendingIrqlMask, PendingIrql; 01073 01074 /* Check for pending software interrupts and compare with current IRQL */ 01075 PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql]; 01076 if (PendingIrqlMask) 01077 { 01078 /* Check for in-service delayed interrupt */ 01079 if (Pcr->IrrActive & 0xFFFFFFF0) return; 01080 01081 /* Check if pending IRQL affects hardware state */ 01082 BitScanReverse(&PendingIrql, PendingIrqlMask); 01083 01084 /* Clear IRR bit */ 01085 Pcr->IRR ^= (1 << PendingIrql); 01086 01087 /* Now handle pending interrupt */ 01088 SWInterruptHandlerTable[PendingIrql](); 01089 } 01090 } 01091 01092 /* SYSTEM INTERRUPTS **********************************************************/ 01093 01094 /* 01095 * @implemented 01096 */ 01097 BOOLEAN 01098 NTAPI 01099 HalEnableSystemInterrupt(IN ULONG Vector, 01100 IN KIRQL Irql, 01101 IN KINTERRUPT_MODE InterruptMode) 01102 { 01103 ULONG Irq; 01104 PKPCR Pcr = KeGetPcr(); 01105 PIC_MASK PicMask; 01106 01107 /* Validate the IRQ */ 01108 Irq = Vector - PRIMARY_VECTOR_BASE; 01109 if (Irq >= CLOCK2_LEVEL) return FALSE; 01110 01111 /* Check for level interrupt */ 01112 if (InterruptMode == LevelSensitive) 01113 { 01114 /* Switch handler to level */ 01115 SWInterruptHandlerTable[Irq + 4] = HalpHardwareInterruptLevel; 01116 01117 /* Switch dismiss to level */ 01118 HalpSpecialDismissTable[Irq] = HalpSpecialDismissLevelTable[Irq]; 01119 } 01120 01121 /* Disable interrupts */ 01122 _disable(); 01123 01124 /* Update software IDR */ 01125 Pcr->IDR &= ~(1 << Irq); 01126 01127 /* Set new PIC mask */ 01128 PicMask.Both = (KiI8259MaskTable[Pcr->Irql] | Pcr->IDR) & 0xFFFF; 01129 __outbyte(PIC1_DATA_PORT, PicMask.Master); 01130 __outbyte(PIC2_DATA_PORT, PicMask.Slave); 01131 01132 /* Enable interrupts and exit */ 01133 _enable(); 01134 return TRUE; 01135 } 01136 01137 /* 01138 * @implemented 01139 */ 01140 VOID 01141 NTAPI 01142 HalDisableSystemInterrupt(IN ULONG Vector, 01143 IN KIRQL Irql) 01144 { 01145 ULONG IrqMask; 01146 PIC_MASK PicMask; 01147 01148 /* Compute new combined IRQ mask */ 01149 IrqMask = 1 << (Vector - PRIMARY_VECTOR_BASE); 01150 01151 /* Disable interrupts */ 01152 _disable(); 01153 01154 /* Update software IDR */ 01155 KeGetPcr()->IDR |= IrqMask; 01156 01157 /* Read current interrupt mask */ 01158 PicMask.Master = __inbyte(PIC1_DATA_PORT); 01159 PicMask.Slave = __inbyte(PIC2_DATA_PORT); 01160 01161 /* Add the new disabled interrupt */ 01162 PicMask.Both |= IrqMask; 01163 01164 /* Write new interrupt mask */ 01165 __outbyte(PIC1_DATA_PORT, PicMask.Master); 01166 __outbyte(PIC2_DATA_PORT, PicMask.Slave); 01167 01168 /* Bring interrupts back */ 01169 _enable(); 01170 } 01171 01172 /* 01173 * @implemented 01174 */ 01175 BOOLEAN 01176 NTAPI 01177 HalBeginSystemInterrupt(IN KIRQL Irql, 01178 IN ULONG Vector, 01179 OUT PKIRQL OldIrql) 01180 { 01181 ULONG Irq; 01182 01183 /* Get the IRQ and call the proper routine to handle it */ 01184 Irq = Vector - PRIMARY_VECTOR_BASE; 01185 return HalpSpecialDismissTable[Irq](Irql, Irq, OldIrql); 01186 } 01187 01188 /* 01189 * @implemented 01190 */ 01191 VOID 01192 NTAPI 01193 HalEndSystemInterrupt(IN KIRQL OldIrql, 01194 IN PKTRAP_FRAME TrapFrame) 01195 { 01196 ULONG PendingIrql, PendingIrqlMask, PendingIrqMask; 01197 PKPCR Pcr = KeGetPcr(); 01198 PIC_MASK Mask; 01199 01200 /* Set old IRQL */ 01201 Pcr->Irql = OldIrql; 01202 01203 /* Check for pending software interrupts and compare with current IRQL */ 01204 PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; 01205 if (PendingIrqlMask) 01206 { 01207 /* Check for in-service delayed interrupt */ 01208 if (Pcr->IrrActive & 0xFFFFFFF0) return; 01209 01210 /* Loop checking for pending interrupts */ 01211 while (TRUE) 01212 { 01213 /* Check if pending IRQL affects hardware state */ 01214 BitScanReverse(&PendingIrql, PendingIrqlMask); 01215 if (PendingIrql > DISPATCH_LEVEL) 01216 { 01217 /* Set new PIC mask */ 01218 Mask.Both = Pcr->IDR & 0xFFFF; 01219 __outbyte(PIC1_DATA_PORT, Mask.Master); 01220 __outbyte(PIC2_DATA_PORT, Mask.Slave); 01221 01222 /* Now check if this specific interrupt is already in-service */ 01223 PendingIrqMask = (1 << PendingIrql); 01224 if (Pcr->IrrActive & PendingIrqMask) return; 01225 01226 /* Set active bit otherwise, and clear it from IRR */ 01227 Pcr->IrrActive |= PendingIrqMask; 01228 Pcr->IRR ^= PendingIrqMask; 01229 01230 /* Handle delayed hardware interrupt */ 01231 SWInterruptHandlerTable[PendingIrql](); 01232 01233 /* Handling complete */ 01234 Pcr->IrrActive ^= PendingIrqMask; 01235 01236 /* Check if there's still interrupts pending */ 01237 PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql]; 01238 if (!PendingIrqlMask) break; 01239 } 01240 else 01241 { 01242 /* Now handle pending software interrupt */ 01243 SWInterruptHandlerTable2[PendingIrql](TrapFrame); 01244 } 01245 } 01246 } 01247 } 01248 01249 /* SOFTWARE INTERRUPT TRAPS ***************************************************/ 01250 01251 VOID 01252 FORCEINLINE 01253 DECLSPEC_NORETURN 01254 _HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) 01255 { 01256 KIRQL CurrentIrql; 01257 PKPCR Pcr = KeGetPcr(); 01258 01259 /* Save the current IRQL and update it */ 01260 CurrentIrql = Pcr->Irql; 01261 Pcr->Irql = APC_LEVEL; 01262 01263 /* Remove DPC from IRR */ 01264 Pcr->IRR &= ~(1 << APC_LEVEL); 01265 01266 /* Enable interrupts and call the kernel's APC interrupt handler */ 01267 _enable(); 01268 KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ? 01269 UserMode : KernelMode, 01270 NULL, 01271 TrapFrame); 01272 01273 /* Disable interrupts and end the interrupt */ 01274 _disable(); 01275 HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame); 01276 01277 /* Exit the interrupt */ 01278 KiEoiHelper(TrapFrame); 01279 } 01280 01281 VOID 01282 DECLSPEC_NORETURN 01283 FASTCALL 01284 HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) 01285 { 01286 /* Do the work */ 01287 _HalpApcInterruptHandler(TrapFrame); 01288 } 01289 01290 VOID 01291 DECLSPEC_NORETURN 01292 FASTCALL 01293 HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) 01294 { 01295 /* Set up a fake INT Stack */ 01296 TrapFrame->EFlags = __readeflags(); 01297 TrapFrame->SegCs = KGDT_R0_CODE; 01298 TrapFrame->Eip = TrapFrame->Eax; 01299 01300 /* Build the trap frame */ 01301 KiEnterInterruptTrap(TrapFrame); 01302 01303 /* Do the work */ 01304 _HalpApcInterruptHandler(TrapFrame); 01305 } 01306 01307 KIRQL 01308 FORCEINLINE 01309 _HalpDispatchInterruptHandler(VOID) 01310 { 01311 KIRQL CurrentIrql; 01312 PKPCR Pcr = KeGetPcr(); 01313 01314 /* Save the current IRQL and update it */ 01315 CurrentIrql = Pcr->Irql; 01316 Pcr->Irql = DISPATCH_LEVEL; 01317 01318 /* Remove DPC from IRR */ 01319 Pcr->IRR &= ~(1 << DISPATCH_LEVEL); 01320 01321 /* Enable interrupts and call the kernel's DPC interrupt handler */ 01322 _enable(); 01323 KiDispatchInterrupt(); 01324 _disable(); 01325 01326 /* Return IRQL */ 01327 return CurrentIrql; 01328 } 01329 01330 VOID 01331 DECLSPEC_NORETURN 01332 FASTCALL 01333 HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) 01334 { 01335 KIRQL CurrentIrql; 01336 01337 /* Do the work */ 01338 CurrentIrql = _HalpDispatchInterruptHandler(); 01339 01340 /* End the interrupt */ 01341 HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame); 01342 01343 /* Exit the interrupt */ 01344 KiEoiHelper(TrapFrame); 01345 } 01346 01347 VOID 01348 HalpDispatchInterrupt2(VOID) 01349 { 01350 ULONG PendingIrqlMask, PendingIrql; 01351 KIRQL OldIrql; 01352 PIC_MASK Mask; 01353 PKPCR Pcr = KeGetPcr(); 01354 01355 /* Do the work */ 01356 OldIrql = _HalpDispatchInterruptHandler(); 01357 01358 /* Restore IRQL */ 01359 Pcr->Irql = OldIrql; 01360 01361 /* Check for pending software interrupts and compare with current IRQL */ 01362 PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; 01363 if (PendingIrqlMask) 01364 { 01365 /* Check if pending IRQL affects hardware state */ 01366 BitScanReverse(&PendingIrql, PendingIrqlMask); 01367 if (PendingIrql > DISPATCH_LEVEL) 01368 { 01369 /* Set new PIC mask */ 01370 Mask.Both = Pcr->IDR & 0xFFFF; 01371 __outbyte(PIC1_DATA_PORT, Mask.Master); 01372 __outbyte(PIC2_DATA_PORT, Mask.Slave); 01373 01374 /* Clear IRR bit */ 01375 Pcr->IRR ^= (1 << PendingIrql); 01376 } 01377 01378 /* Now handle pending interrupt */ 01379 SWInterruptHandlerTable[PendingIrql](); 01380 } 01381 } 01382 01383 #else 01384 01385 KIRQL 01386 NTAPI 01387 KeGetCurrentIrql(VOID) 01388 { 01389 return PASSIVE_LEVEL; 01390 } 01391 01392 VOID 01393 FASTCALL 01394 KfLowerIrql( 01395 IN KIRQL OldIrql) 01396 { 01397 } 01398 01399 KIRQL 01400 FASTCALL 01401 KfRaiseIrql( 01402 IN KIRQL NewIrql) 01403 { 01404 return NewIrql; 01405 } 01406 01407 #endif Generated on Sat May 26 2012 04:27:16 for ReactOS by
1.7.6.1
|