131 lines
3.1 KiB
C
131 lines
3.1 KiB
C
/*----------------*\
|
|
|Nanite OS |
|
|
|Copyright (C) 2024|
|
|
|Tyler McGurrin |
|
|
\*----------------*/
|
|
#include "pic.h"
|
|
#include "io.h"
|
|
|
|
#define PIC1_COMMAND_PORT 0x20
|
|
#define PIC2_COMMAND_PORT 0xA0
|
|
#define PIC1_DATA_PORT 0x21
|
|
#define PIC2_DATA_PORT 0xA1
|
|
|
|
enum {
|
|
PIC_ICW1_ICW4 = 0x01,
|
|
PIC_ICW1_SINGLE = 0x02,
|
|
PIC_ICW1_INTERVAL4 = 0x02,
|
|
PIC_ICW1_LEVEL = 0x08,
|
|
PIC_ICW1_INITITALIZE = 0x10
|
|
} PIC_ICW1;
|
|
|
|
enum {
|
|
PIC_ICW4_8086 = 0x1,
|
|
PIC_ICW4_AUTO_EDI = 0x2,
|
|
PIC_ICW4_BUFFER_MASTER = 0x4,
|
|
PIC_ICW4_BUFFER_SLAVE = 0x0,
|
|
PIC_ICW4_BUFFERRED = 0x8,
|
|
PIC_ICW4_SFNM = 0x10
|
|
} PIC_ICW4;
|
|
|
|
enum {
|
|
PIC_CMD_END_OF_INTERRUPT = 0x20,
|
|
PIC_CMD_READ_IRR = 0x0A,
|
|
PIC_CMD_READ_ISR = 0x0B
|
|
} PIC_CMD;
|
|
|
|
void i686_PIC_Configure(uint8_t offsetPic1, uint8_t offsetPic2)
|
|
{
|
|
// init control word 1
|
|
i686_outb(PIC1_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITITALIZE);
|
|
i686_iowait();
|
|
i686_outb(PIC2_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITITALIZE);
|
|
i686_iowait();
|
|
|
|
// init control word 2
|
|
i686_outb(PIC1_DATA_PORT, offsetPic1);
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, offsetPic2);
|
|
i686_iowait();
|
|
|
|
// init control word 3
|
|
i686_outb(PIC1_DATA_PORT, PIC_ICW4_BUFFER_MASTER); // tell PIC 1 it has slave at IRQ 2
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, PIC_ICW4_BUFFER_SLAVE); // tell PIC 2 its cascade ID
|
|
i686_iowait();
|
|
|
|
// init control word 4
|
|
i686_outb(PIC1_DATA_PORT, PIC_ICW4_8086);
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, PIC_ICW4_8086);
|
|
i686_iowait();
|
|
|
|
// clear data registers
|
|
i686_outb(PIC1_DATA_PORT, 0);
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, 0);
|
|
i686_iowait();
|
|
}
|
|
|
|
void i686_PIC_Mask(int irq)
|
|
{
|
|
uint8_t port;
|
|
|
|
if (irq < 8)
|
|
{
|
|
port = PIC1_DATA_PORT;
|
|
}
|
|
else
|
|
{
|
|
irq -=8;
|
|
port = PIC2_DATA_PORT;
|
|
}
|
|
uint8_t mask = i686_inb(port);
|
|
i686_outb(port, mask | (1 << irq));
|
|
}
|
|
|
|
void i686_PIC_Unmask(int irq)
|
|
{
|
|
uint8_t port;
|
|
|
|
if (irq < 8)
|
|
{
|
|
port = PIC1_DATA_PORT;
|
|
}
|
|
else
|
|
{
|
|
irq -=8;
|
|
port = PIC2_DATA_PORT;
|
|
}
|
|
uint8_t mask = i686_inb(port);
|
|
i686_outb(port, mask & ~(1 << irq));
|
|
}
|
|
|
|
void i686_PIC_Disable()
|
|
{
|
|
i686_outb(PIC1_DATA_PORT, 0xFF);
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, 0xFF);
|
|
i686_iowait();
|
|
}
|
|
|
|
void i686_PIC_SendEndOfInterrupt(int irq)
|
|
{
|
|
if (irq >= 8)
|
|
i686_outb(PIC2_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
|
|
i686_outb(PIC1_COMMAND_PORT, PIC_CMD_END_OF_INTERRUPT);
|
|
}
|
|
|
|
uint16_t i686_PIC_ReadIRQRequestRegister()
|
|
{
|
|
i686_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_IRR);
|
|
i686_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_IRR);
|
|
return i686_inb(PIC2_COMMAND_PORT) | (i686_inb(PIC2_COMMAND_PORT) << 8);
|
|
}
|
|
|
|
uint16_t i686_PIC_ReadInServiceRegister()
|
|
{
|
|
i686_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_ISR);
|
|
i686_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_ISR);
|
|
return i686_inb(PIC2_COMMAND_PORT) | (i686_inb(PIC2_COMMAND_PORT) << 8);
|
|
} |