2018-10-16 09:01:38 +00:00
|
|
|
#include "types.h"
|
|
|
|
#include "i386.h"
|
|
|
|
#include "IO.h"
|
|
|
|
#include "PIC.h"
|
|
|
|
#include "Assertions.h"
|
|
|
|
|
|
|
|
// The slave 8259 is connected to the master's IRQ2 line.
|
|
|
|
// This is really only to enhance clarity.
|
|
|
|
#define SLAVE_INDEX 2
|
|
|
|
|
|
|
|
#define PIC0_CTL 0x20
|
|
|
|
#define PIC0_CMD 0x21
|
|
|
|
#define PIC1_CTL 0xA0
|
|
|
|
#define PIC1_CMD 0xA1
|
|
|
|
|
|
|
|
#ifdef DEBUG_PIC
|
|
|
|
static bool initialized;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace PIC {
|
|
|
|
|
2018-11-16 23:11:08 +00:00
|
|
|
void disable(byte irq)
|
2018-10-16 09:01:38 +00:00
|
|
|
{
|
2018-11-16 23:11:08 +00:00
|
|
|
byte imr;
|
2018-10-16 09:01:38 +00:00
|
|
|
if (irq & 8) {
|
|
|
|
imr = IO::in8(PIC1_CMD);
|
|
|
|
imr |= 1 << (irq - 8);
|
|
|
|
IO::out8(PIC1_CMD, imr);
|
|
|
|
} else {
|
|
|
|
imr = IO::in8(PIC0_CMD);
|
|
|
|
imr |= 1 << irq;
|
|
|
|
IO::out8(PIC0_CMD, imr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-16 23:11:08 +00:00
|
|
|
void enable(byte irq)
|
2018-10-16 09:01:38 +00:00
|
|
|
{
|
2018-11-16 23:11:08 +00:00
|
|
|
byte imr;
|
2018-10-16 09:01:38 +00:00
|
|
|
if (irq & 8) {
|
|
|
|
imr = IO::in8(PIC1_CMD);
|
|
|
|
imr &= ~(1 << (irq - 8));
|
|
|
|
IO::out8(PIC1_CMD, imr);
|
|
|
|
} else {
|
|
|
|
imr = IO::in8(PIC0_CMD);
|
|
|
|
imr &= ~(1 << irq);
|
|
|
|
IO::out8(PIC0_CMD, imr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-16 23:11:08 +00:00
|
|
|
void eoi(byte irq)
|
2018-10-16 09:01:38 +00:00
|
|
|
{
|
|
|
|
if (irq & 8)
|
|
|
|
IO::out8(PIC1_CTL, 0x20);
|
2018-10-16 09:05:29 +00:00
|
|
|
IO::out8(PIC0_CTL, 0x20);
|
2018-10-16 09:01:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void initialize()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_PIC
|
|
|
|
ASSERT(!initialized);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ICW1 (edge triggered mode, cascading controllers, expect ICW4) */
|
|
|
|
IO::out8(PIC0_CTL, 0x11);
|
|
|
|
IO::out8(PIC1_CTL, 0x11);
|
|
|
|
|
|
|
|
/* ICW2 (upper 5 bits specify ISR indices, lower 3 idunno) */
|
|
|
|
IO::out8(PIC0_CMD, IRQ_VECTOR_BASE);
|
|
|
|
IO::out8(PIC1_CMD, IRQ_VECTOR_BASE + 0x08);
|
|
|
|
|
|
|
|
/* ICW3 (configure master/slave relationship) */
|
|
|
|
IO::out8(PIC0_CMD, 1 << SLAVE_INDEX);
|
|
|
|
IO::out8(PIC1_CMD, SLAVE_INDEX);
|
|
|
|
|
|
|
|
/* ICW4 (set x86 mode) */
|
|
|
|
IO::out8(PIC0_CMD, 0x01);
|
|
|
|
IO::out8(PIC1_CMD, 0x01 );
|
|
|
|
|
2018-10-22 09:15:16 +00:00
|
|
|
// Mask -- start out with all IRQs disabled.
|
|
|
|
IO::out8(PIC0_CMD, 0xff);
|
|
|
|
IO::out8(PIC1_CMD, 0xff);
|
|
|
|
|
|
|
|
// ...except IRQ2, since that's needed for the master to let through slave interrupts.
|
|
|
|
enable(2);
|
2018-10-16 09:01:38 +00:00
|
|
|
|
|
|
|
kprintf("PIC(i8259): cascading mode, vectors 0x%b-0x%b\n", IRQ_VECTOR_BASE, IRQ_VECTOR_BASE + 0x08);
|
|
|
|
|
|
|
|
#ifdef DEBUG_PIC
|
|
|
|
initialized = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-01-31 16:31:23 +00:00
|
|
|
word get_isr()
|
2018-10-17 14:53:06 +00:00
|
|
|
{
|
|
|
|
IO::out8(PIC0_CTL, 0x0b);
|
|
|
|
IO::out8(PIC1_CTL, 0x0b);
|
|
|
|
byte isr0 = IO::in8(PIC0_CTL);
|
|
|
|
byte isr1 = IO::in8(PIC1_CTL);
|
|
|
|
return (isr1 << 8) | isr0;
|
|
|
|
}
|
|
|
|
|
2018-11-10 14:15:31 +00:00
|
|
|
word get_irr()
|
|
|
|
{
|
|
|
|
IO::out8(PIC0_CTL, 0x0a);
|
|
|
|
IO::out8(PIC1_CTL, 0x0a);
|
|
|
|
byte irr0 = IO::in8(PIC0_CTL);
|
|
|
|
byte irr1 = IO::in8(PIC1_CTL);
|
|
|
|
return (irr1 << 8) | irr0;
|
|
|
|
}
|
|
|
|
|
2018-10-16 09:01:38 +00:00
|
|
|
}
|