ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pic.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.