[HAL]
[reactos.git] / reactos / hal / halx86 / generic / amd64 / pic.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: hal/pic.c
5 * PURPOSE: Hardware Abstraction Layer DLL
6 * PROGRAMMER: Samuel SerapiĆ³n
7 */
8 #include <hal.h>
9
10 //#define NDEBUG
11 #include <debug.h>
12 #include <asm.h>
13
14 /*
15 * 8259 interrupt controllers
16 */
17 enum
18 {
19 Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
20 Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
21 Int1ctl= 0xA0, /* control port */
22 Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
23
24 Icw1= 0x10, /* select bit in ctl register */
25 Ocw2= 0x00,
26 Ocw3= 0x08,
27
28 EOI= 0x20, /* non-specific end of interrupt */
29
30 Elcr1= 0x4D0, /* Edge/Level Triggered Register */
31 Elcr2= 0x4D1,
32 };
33
34
35
36 INT i8259mask = 0xFFFF; /* disabled interrupts */
37 INT i8259elcr;
38
39
40 VOID
41 NTAPI
42 HalpInitPICs(VOID)
43 {
44 ULONG OldEflags;
45 INT x;
46
47 OldEflags = __readeflags();
48 _disable();
49
50 /*
51 * Set up the first 8259 interrupt processor.
52 * Make 8259 interrupts start at CPU vector VectorPIC.
53 * Set the 8259 as master with edge triggered
54 * input with fully nested interrupts.
55 */
56 __outbyte(Int0ctl, 0x20); /* ICW1 - master, edge triggered */
57 __outbyte(Int0aux, 0x11); /* Edge, cascade, CAI 8, ICW4 */
58 __outbyte(Int0aux, PRIMARY_VECTOR_BASE); /* ICW2 - interrupt vector offset */
59 __outbyte(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
60 __outbyte(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
61 __outbyte(Int0aux, 0xFF); /* Mask Interrupts */
62 /*
63 * Set up the second 8259 interrupt processor.
64 * Make 8259 interrupts start at CPU vector VectorPIC+8.
65 * Set the 8259 as slave with edge triggered
66 * input with fully nested interrupts.
67 */
68 __outbyte(Int1ctl, 0xA0); /* ICW1 - master, edge triggered, */
69 __outbyte(Int1aux, 0x11); /* Edge, cascade, CAI 8, ICW4 */
70 __outbyte(Int1aux, PRIMARY_VECTOR_BASE+8); /* ICW2 - interrupt vector offset */
71 __outbyte(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
72 __outbyte(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
73 __outbyte(Int1aux, 0xFF); /* Mask Interrupts */
74
75
76 /*
77 * pass #2 8259 interrupts to #1
78 */
79 i8259mask &= ~0x04;
80 __outbyte(Int0aux, i8259mask & 0xFF);
81
82 /*
83 * Set Ocw3 to return the ISR when ctl read.
84 * After initialisation status read is set to IRR.
85 * Read IRR first to possibly deassert an outstanding
86 * interrupt.
87 */
88 __inbyte (Int0ctl);
89 __outbyte(Int0ctl, Ocw3|0x03);
90 __inbyte (Int1ctl);
91 __outbyte(Int1ctl, Ocw3|0x03);
92
93 /*
94 * Check for Edge/Level register.
95 * This check may not work for all chipsets.
96 * First try a non-intrusive test - the bits for
97 * IRQs 13, 8, 2, 1 and 0 must be edge (0). If
98 * that's OK try a R/W test.
99 */
100 x = (__inbyte(Elcr2) << 8) | __inbyte(Elcr1);
101
102 if (!(x & 0x2107))
103 {
104 __outbyte(Elcr1, 0);
105
106 if (__inbyte (Elcr1) == 0)
107 {
108 __outbyte(Elcr1, 0x20);
109
110 if (__inbyte (Elcr1) == 0x20)
111 {
112 i8259elcr = x;
113 }
114 __outbyte(Elcr1, x & 0xFF);
115 DPRINT("ELCR: %4.4uX\n", i8259elcr);
116 }
117 }
118
119 __writeeflags(OldEflags);
120 }
121
122 VOID
123 NTAPI
124 HalDisableSystemInterrupt(
125 ULONG Vector,
126 KIRQL Irql)
127 {
128 UNIMPLEMENTED;
129 }
130
131 BOOLEAN
132 NTAPI
133 HalEnableSystemInterrupt(
134 ULONG Vector,
135 KIRQL Irql,
136 KINTERRUPT_MODE InterruptMode)
137 {
138 UNIMPLEMENTED;
139 return FALSE;
140 }
141