Merge from amd64-branch:
[reactos.git] / reactos / hal / halx86 / generic / pic.c
1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: hal/halx86/generic/pic.c
5 * PURPOSE: HAL PIC Management and Control Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 USHORT HalpEisaELCR;
18
19 /* FUNCTIONS ******************************************************************/
20
21 VOID
22 NTAPI
23 HalpInitializePICs(IN BOOLEAN EnableInterrupts)
24 {
25 ULONG EFlags;
26 I8259_ICW1 Icw1;
27 I8259_ICW2 Icw2;
28 I8259_ICW3 Icw3;
29 I8259_ICW4 Icw4;
30 EISA_ELCR Elcr;
31 ULONG i, j;
32
33 /* Save EFlags and disable interrupts */
34 EFlags = __readeflags();
35 _disable();
36
37 /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */
38 Icw1.NeedIcw4 = TRUE;
39 Icw1.OperatingMode = Cascade;
40 Icw1.Interval = Interval8;
41 Icw1.Init = TRUE;
42 Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */
43 __outbyte(PIC1_CONTROL_PORT, Icw1.Bits);
44
45 /* Set interrupt vector base */
46 Icw2.Bits = PRIMARY_VECTOR_BASE;
47 __outbyte(PIC1_DATA_PORT, Icw2.Bits);
48
49 /* Connect slave to IRQ 2 */
50 Icw3.Bits = 0;
51 Icw3.SlaveIrq2 = TRUE;
52 __outbyte(PIC1_DATA_PORT, Icw3.Bits);
53
54 /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */
55 Icw4.Reserved = 0;
56 Icw4.SystemMode = New8086Mode;
57 Icw4.EoiMode = NormalEoi;
58 Icw4.BufferedMode = NonBuffered;
59 Icw4.SpecialFullyNestedMode = FALSE;
60 __outbyte(PIC1_DATA_PORT, Icw4.Bits);
61
62 /* Mask all interrupts */
63 __outbyte(PIC1_DATA_PORT, 0xFF);
64
65 /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */
66 Icw1.NeedIcw4 = TRUE;
67 Icw1.OperatingMode = Cascade;
68 Icw1.Interval = Interval8;
69 Icw1.Init = TRUE;
70 Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */
71 __outbyte(PIC2_CONTROL_PORT, Icw1.Bits);
72
73 /* Set interrupt vector base */
74 Icw2.Bits = PRIMARY_VECTOR_BASE + 8;
75 __outbyte(PIC2_DATA_PORT, Icw2.Bits);
76
77 /* Slave ID */
78 Icw3.Bits = 0;
79 Icw3.SlaveId = 2;
80 __outbyte(PIC2_DATA_PORT, Icw3.Bits);
81
82 /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */
83 Icw4.Reserved = 0;
84 Icw4.SystemMode = New8086Mode;
85 Icw4.EoiMode = NormalEoi;
86 Icw4.BufferedMode = NonBuffered;
87 Icw4.SpecialFullyNestedMode = FALSE;
88 __outbyte(PIC2_DATA_PORT, Icw4.Bits);
89
90 /* Mask all interrupts */
91 __outbyte(PIC2_DATA_PORT, 0xFF);
92
93 /* Read EISA Edge/Level Register for master and slave */
94 Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER);
95
96 /* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */
97 if (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) &&
98 !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level))
99 {
100 /* ELCR is as it's supposed to be, save it */
101 HalpEisaELCR = Elcr.Bits;
102 DPRINT1("HAL Detected EISA Interrupt Controller (ELCR: %lx)\n", HalpEisaELCR);
103
104 /* Scan for level interrupts */
105 for (i = 1, j = 0; j < 16; i <<= 1, j++)
106 {
107 /* Warn the user ReactOS does not (and has never) supported this */
108 if (HalpEisaELCR & i) DPRINT1("WARNING: IRQ %d is SHARED and LEVEL-SENSITIVE. This is unsupported!\n", j);
109 }
110 }
111
112 /* Restore interrupt state */
113 if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK;
114 __writeeflags(EFlags);
115 }
116