trios/kernel/interrupt/pic.c

81 lines
1.5 KiB
C

#include "pic.h"
#include "../term.h"
#include <sys.h>
#define PIC1_COMMAND_PORT 0x20
#define PIC1_DATA_PORT 0x21
#define PIC2_COMMAND_PORT 0xA0
#define PIC2_DATA_PORT 0xA1
void pic_remap(uint8_t offset) {
char a1 = inb(PIC1_DATA_PORT);
char a2 = inb(PIC2_DATA_PORT);
// control word 1
// 0x11: initialize, enable ICW4
outb(PIC1_COMMAND_PORT, 0x11);
io_wait();
outb(PIC2_COMMAND_PORT, 0x11);
io_wait();
// control word 2
// interrupt offset
outb(PIC1_DATA_PORT, offset);
io_wait();
outb(PIC2_DATA_PORT, offset + 8);
io_wait();
// control word 3
// primary pic: set which pin secondary is connected to
// (pin 2)
outb(PIC1_DATA_PORT, 0b00000100);
io_wait();
outb(PIC2_DATA_PORT, 2);
io_wait();
// control word 3
// 0x01: enable 8086 mode
outb(PIC1_DATA_PORT, 0x01);
io_wait();
outb(PIC2_DATA_PORT, 0x01);
io_wait();
// clear data registers
outb(PIC1_DATA_PORT, a1);
outb(PIC2_DATA_PORT, a2);
}
void pic_mask(int irq) {
uint8_t port;
if(irq < 8) {
port = PIC1_DATA_PORT;
} else {
irq -= 8;
port = PIC2_DATA_PORT;
}
uint8_t mask = inb(port);
outb(port, mask | (1 << irq));
}
void pic_unmask(int irq) {
uint8_t port;
if(irq < 8) {
port = PIC1_DATA_PORT;
} else {
irq -= 8;
port = PIC2_DATA_PORT;
}
uint8_t mask = inb(port);
outb(port, mask & ~(1 << irq));
}
void pic_disable(void) {
outb(PIC1_DATA_PORT, 0xff);
io_wait();
outb(PIC2_DATA_PORT, 0xff);
io_wait();
}
void pic_eoi(int irq) {
if(irq >= 8) {
outb(PIC2_COMMAND_PORT, 0x20);
}
outb(PIC1_COMMAND_PORT, 0x20);
}