81 lines
1.5 KiB
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);
|
|
}
|