1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include <mos/types.h>
4#include <mos/x86/devices/port.h>
5#include <mos/x86/x86_platform.h>
6
7// Reinitialize the PIC controllers.
8// Giving them specified vector offsets rather than 8h and 70h, as configured by default
9// ICW: Initialization command words
10#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
11#define ICW1_INIT 0x10 /* Initialization - required! */
12#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
13
14#define PIC1 0x20 // IO base address for master PIC
15#define PIC2 0xA0 // IO base address for slave PIC
16#define PIC1_COMMAND (PIC1)
17#define PIC1_DATA (PIC1 + 1)
18#define PIC2_COMMAND (PIC2)
19#define PIC2_DATA (PIC2 + 1)
20
21#define PIC1_OFFSET 0x20
22#define PIC2_OFFSET 0x28
23
24// We now have APIC, so PIC is not used anymore, but the above initialization code is still used
25void pic_remap_irq(void)
26{
27 port_outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode)
28 port_outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
29
30 port_outb(PIC1_DATA, PIC1_OFFSET); // ICW2: Master PIC vector offset
31 port_outb(PIC2_DATA, PIC2_OFFSET); // ICW2: Slave PIC vector offset
32
33 port_outb(PIC1_DATA, value: 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
34 port_outb(PIC2_DATA, value: 2); // ICW3: tell Slave PIC its cascade identity (0000 0010)
35
36 port_outb(PIC1_DATA, ICW4_8086);
37 port_outb(PIC2_DATA, ICW4_8086);
38
39 port_outb(PIC2_DATA, value: 0xFF); // mask all interrupts on slave PIC
40 port_outb(PIC1_DATA, value: 0xFF); // mask all interrupts on master PIC
41}
42