59 lines
1.9 KiB
C
59 lines
1.9 KiB
C
#include "../includes/pic.h"
|
|
#include "../includes/io.h"
|
|
#include "../includes/idt.h"
|
|
#include "../includes/irq.h"
|
|
|
|
#define PIC1_PORT 0x20
|
|
#define PIC1_DATA_PORT 0X21
|
|
#define PIC2_PORT 0xA0
|
|
#define PIC2_DATA_PORT 0XA1
|
|
|
|
#define PIC1_START_INTERRUPT 0x20
|
|
#define PIC2_START_INTERRUPT 0x28
|
|
#define PIC2_END_INTERRUPT PIC2_START_INTERRUPT + 7
|
|
|
|
#define PIC_ACK 0x20
|
|
|
|
void pic_acknowledge(unsigned int interrupt_no)
|
|
{
|
|
if (interrupt_no < PIC2_START_INTERRUPT)
|
|
outb(PIC1_PORT, PIC_ACK);
|
|
else
|
|
outb(PIC2_PORT, PIC_ACK);
|
|
}
|
|
|
|
void setup_pics(void)
|
|
{
|
|
// The PIC uses Initialization Command Words (ICW) to communicate.
|
|
// So we start with the first ICW, 0x11, this tells the PIC to expect
|
|
// 3 more ICWs.
|
|
outb(PIC1_PORT, 0x11);
|
|
outb(PIC2_PORT, 0x11);
|
|
|
|
// This tells the pic what offset to use when it generates the interrupt numbers.
|
|
// Since the first 32 ISRs are reserved by the CPU we must start at IRS32 and work
|
|
// our way up. When the PIC recieves an interrupt on it's input line, it will add
|
|
// the supplied values to that number before sending the newly made number to the CPU.
|
|
// Thereby remapping an interrupt number that would have normally conflicted with the
|
|
// values in the IDT.
|
|
outb(PIC1_DATA_PORT, PIC1_START_INTERRUPT);
|
|
outb(PIC2_DATA_PORT, PIC2_START_INTERRUPT);
|
|
|
|
// This ICW allows for cascading of their outputs to inputs between each other.
|
|
// I'm not sure what that really means but at this current time I'm not going to
|
|
// be doing this, so the bits will all be set to zero.
|
|
outb(PIC1_DATA_PORT, 0x00);
|
|
outb(PIC2_DATA_PORT, 0x00);
|
|
|
|
// This is the environment info, and setting the lowest bit tells the PICs
|
|
// that we're running in 80x86 mode.
|
|
outb(PIC1_DATA_PORT, 0x01);
|
|
outb(PIC2_DATA_PORT, 0x01);
|
|
|
|
// Finally, we have the interrupt masks.
|
|
outb(PIC1_DATA_PORT, 0xFF);
|
|
outb(PIC2_DATA_PORT, 0xFF);
|
|
|
|
idt_set_gate(33, (unsigned long) &irq1, 0x08, 0x8E);
|
|
}
|