AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
pic.c
Go to the documentation of this file.
1
9
10#include <core/system.h>
11#include <core/panic.h>
12
13#include <core/arch.h>
14#include <platform/misc.h>
15#include <sys/sched.h>
16#include <sys/signal.h>
17#include <cpu/cpu.h>
18
19#define PIC_CMD 0x00
20#define PIC_DATA 0x01
21
22static struct ioaddr master;
23static struct ioaddr slave;
24
25/*
26 * The 8259s are set up with four initialization command words (ICWs):
27 *
28 * - ICW1, on each one's command port, starts the setup: edge-triggered,
29 * cascaded (two 8259s), with an ICW4 to come;
30 * - ICW2, on the data port, is the vector of its first IRQ: 32 for the
31 * master, 40 for the slave, past the CPU's exceptions;
32 * - ICW3 says how they are cascaded: the master has the slave on its IRQ
33 * 2, and the slave's ID is 2;
34 * - ICW4 sets 8086 mode.
35 */
36
37#define ICW1 0x11 /* the same for the master and the slave */
38#define ICW2_MASTER 0x20 /* the master's IRQs are vectors 32 and up */
39#define ICW2_SLAVE 0x28 /* the slave's are vectors 40 and up */
40#define ICW3_MASTER 0x04 /* the master has the slave on its IRQ 2 */
41#define ICW3_SLAVE 0x02 /* the slave's ID is 2 */
42#define ICW4 0x01 /* 8086 mode */
43
44/* the masks the 8259s have now: the slave's in the high byte */
45static uint16_t pic_mask = 0xFFFF;
46
48static void x86_irq_mask(int irq)
49{
50 if (irq < 8) { /* the master's */
51 pic_mask |= 1 << irq;
53 } else if (irq < 16) { /* the slave's */
54 pic_mask |= 1 << irq;
55 io_out8(&slave, PIC_DATA, (pic_mask >> 8) & 0xFF);
56 } else {
57 panic("Invalid IRQ number\n");
58 }
59}
60
62static void x86_irq_unmask(int irq)
63{
64 if (irq < 8) { /* the master's */
65 pic_mask &= ~(1 << irq);
67 } else if (irq < 16) { /* the slave's */
68 pic_mask &= ~(1 << irq);
69 pic_mask &= ~(1 << 2); /* and the master's IRQ 2, where the slave is */
70 io_out8(&slave, PIC_DATA, (pic_mask >> 8) & 0xFF);
72 } else {
73 panic("Invalid IRQ number\n");
74 }
75}
76
90
91#define IRQ_ACK 0x20
92
95static void pic_chip_eoi(unsigned irq)
96{
97 if (irq >= 16)
98 return;
99
100 if (irq > 7) /* the slave's IRQ */
102
104}
105
107static void pic_chip_mask(unsigned irq)
108{
109 if (irq < 16)
110 x86_irq_mask(irq);
111}
112
114static void pic_chip_unmask(unsigned irq)
115{
116 if (irq < 16)
117 x86_irq_unmask(irq);
118}
119
121static const char *pic_chip_describe(unsigned irq)
122{
123 return irq < 16 ? "8259 edge" : "";
124}
125
127 .name = "8259",
128 .mask = pic_chip_mask,
129 .unmask = pic_chip_unmask,
130 .eoi = pic_chip_eoi,
131 .describe = pic_chip_describe,
132};
133
136static int x86_pic_probe(void)
137{
138 /* mask all of the slave's IRQs */
139 io_out8(&slave, PIC_DATA, 0xFF);
140
141 /* mask all of the master's IRQs, but IRQ 2, where the slave is */
142 io_out8(&master, PIC_DATA, 0xFB);
143
144 /* a device answers if it kept the mask */
145 if (io_in8(&master, PIC_DATA) != 0xFB)
146 return -ENODEV;
147
148 return 0;
149}
150
153{
154 io_out8(&slave, PIC_DATA, 0xFF);
155 io_out8(&master, PIC_DATA, 0xFF);
156}
157
165int x86_pic_setup(struct ioaddr *_master, struct ioaddr *_slave)
166{
167 master = *_master;
168 slave = *_slave;
169
170 if (x86_pic_probe()) {
171 printk("i8259: Controller not found\n");
172 return -ENODEV;
173 }
174
175 printk("i8259: initializing [Master: %p (%s), Slave: %p (%s)]\n",
178
180
181 /* every IRQ masked, until it has a handler */
183 return 0;
184}
static uint8_t io_in8(struct ioaddr *io, uintptr_t off)
Reads an 8-, 16- or 32-bit register.
Definition io.h:28
static void io_out8(struct ioaddr *io, uintptr_t off, uint8_t val)
Writes an 8-, 16- or 32-bit register.
Definition io.h:44
#define panic(s)
Definition panic.h:15
static char * ioaddr_type_str(struct ioaddr *io)
Definition io.h:101
int x86_pic_setup(struct ioaddr *master, struct ioaddr *slave)
Sets up the 8259s, with every IRQ masked.
Definition pic.c:165
void x86_pic_disable(void)
Masks every IRQ of the 8259s, when the APIC brings the interrupts.
Definition pic.c:152
struct x86_irq_chip x86_pic_chip
Definition pic.c:126
static void x86_irq_remap(void)
Initializes the 8259s, with their IRQs at vectors 32 to 47, so that they don't collide with the CPU's...
Definition pic.c:79
static void x86_irq_unmask(int irq)
Unmasks an IRQ at its 8259 (for the slave's, the master's IRQ 2 too).
Definition pic.c:62
#define PIC_DATA
Definition pic.c:20
#define IRQ_ACK
Definition pic.c:91
#define PIC_CMD
Definition pic.c:19
#define ICW2_SLAVE
Definition pic.c:39
#define ICW3_MASTER
Definition pic.c:40
static void pic_chip_eoi(unsigned irq)
Tells the 8259s that an interrupt is handled: the slave too for its own IRQs.
Definition pic.c:95
#define ICW4
Definition pic.c:42
static struct ioaddr slave
Definition pic.c:23
#define ICW3_SLAVE
Definition pic.c:41
#define ICW2_MASTER
Definition pic.c:38
static void pic_chip_unmask(unsigned irq)
Unmasks an IRQ, for irq.c.
Definition pic.c:114
#define ICW1
Definition pic.c:37
static int x86_pic_probe(void)
Checks that there is an 8259 at the master's ports: it must keep the mask that was written.
Definition pic.c:136
static struct ioaddr master
Definition pic.c:22
static void pic_chip_mask(unsigned irq)
Masks an IRQ, for irq.c.
Definition pic.c:107
static const char * pic_chip_describe(unsigned irq)
Describes an IRQ's route, for /proc/interrupts.
Definition pic.c:121
static void x86_irq_mask(int irq)
Masks an IRQ at its 8259.
Definition pic.c:48
static uint16_t pic_mask
Definition pic.c:45
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
unsigned short int uint16_t
Definition stddef.h:21
Where a device's registers are.
Definition io.h:95
uintptr_t addr
Definition io.h:97
An interrupt controller: the 8259s, or the APIC.
Definition misc.h:20