58217f5900
WOO HOO!
149 lines
No EOL
4.3 KiB
C
149 lines
No EOL
4.3 KiB
C
#include "pic.h"
|
|
#include "io.h"
|
|
|
|
#define PIC1_COMMAND_PORT 0x20
|
|
#define PIC1_DATA_PORT 0x21
|
|
#define PIC2_COMMAND_PORT 0xA0
|
|
#define PIC2_DATA_PORT 0xA1
|
|
|
|
// Initialization Control Word 1
|
|
// -----------------------------
|
|
// 0 IC4 if set, the PIC expects to receive ICW4 during initialization
|
|
// 1 SGNL if set, only 1 PIC in the system; if unset, the PIC is cascaded with slave PICs
|
|
// and ICW3 must be sent to controller
|
|
// 2 ADI call address interval, set: 4, not set: 8; ignored on x86, set to 0
|
|
// 3 LTIM if set, operate in level triggered mode; if unset, operate in edge triggered mode
|
|
// 4 INIT set to 1 to initialize PIC
|
|
// 5-7 ignored on x86, set to 0
|
|
|
|
enum {
|
|
PIC_ICW1_ICW4 = 0x01,
|
|
PIC_ICW1_SINGLE = 0x02,
|
|
PIC_ICW1_INTERVAL4 = 0x04,
|
|
PIC_ICW1_LEVEL = 0x08,
|
|
PIC_ICW1_INITIALIZE = 0x10
|
|
} PIC_ICW1;
|
|
|
|
|
|
// Initialization Control Word 4
|
|
// -----------------------------
|
|
// 0 uPM if set, PIC is in 80x86 mode; if cleared, in MCS-80/85 mode
|
|
// 1 AEOI if set, on last interrupt acknowledge pulse, controller automatically performs
|
|
// end of interrupt operation
|
|
// 2 M/S only use if BUF is set; if set, selects buffer master; otherwise, selects buffer slave
|
|
// 3 BUF if set, controller operates in buffered mode
|
|
// 4 SFNM specially fully nested mode; used in systems with large number of cascaded controllers
|
|
// 5-7 reserved, set to 0
|
|
enum {
|
|
PIC_ICW4_8086 = 0x1,
|
|
PIC_ICW4_AUTO_EOI = 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)
|
|
{
|
|
// initialization control word 1
|
|
i686_outb(PIC1_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
|
|
i686_iowait();
|
|
i686_outb(PIC2_COMMAND_PORT, PIC_ICW1_ICW4 | PIC_ICW1_INITIALIZE);
|
|
i686_iowait();
|
|
|
|
// initialization control word 2 - the offsets
|
|
i686_outb(PIC1_DATA_PORT, offsetPic1);
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, offsetPic2);
|
|
i686_iowait();
|
|
|
|
// initialization control word 3
|
|
i686_outb(PIC1_DATA_PORT, 0x4); // tell PIC1 that it has a slave at IRQ2 (0000 0100)
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, 0x2); // tell PIC2 its cascade identity (0000 0010)
|
|
i686_iowait();
|
|
|
|
// initialization 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_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);
|
|
}
|
|
|
|
void i686_PIC_Disable()
|
|
{
|
|
i686_outb(PIC1_DATA_PORT, 0xFF); // mask all
|
|
i686_iowait();
|
|
i686_outb(PIC2_DATA_PORT, 0xFF); // mask all
|
|
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(PIC1_DATA_PORT);
|
|
i686_outb(PIC1_DATA_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(PIC1_DATA_PORT);
|
|
i686_outb(PIC1_DATA_PORT, mask & ~(1 << irq));
|
|
}
|
|
|
|
uint16_t i686_PIC_ReadIrqRequestRegister()
|
|
{
|
|
i686_outb(PIC1_COMMAND_PORT, PIC_CMD_READ_IRR);
|
|
i686_outb(PIC2_COMMAND_PORT, PIC_CMD_READ_IRR);
|
|
return ((uint16_t)i686_inb(PIC2_COMMAND_PORT)) | (((uint16_t)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 ((uint16_t)i686_inb(PIC2_COMMAND_PORT)) | (((uint16_t)i686_inb(PIC2_COMMAND_PORT)) << 8);
|
|
} |