2017-11-24 23:41:14 +01:00
|
|
|
#include "pic.h"
|
|
|
|
#include "io.h"
|
2018-06-26 16:41:06 +02:00
|
|
|
#include "irq.h"
|
2017-11-24 23:41:14 +01:00
|
|
|
|
2018-06-26 16:41:06 +02:00
|
|
|
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
|
|
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
|
|
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
|
|
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
|
|
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
2017-11-24 23:41:14 +01:00
|
|
|
|
2018-06-26 16:41:06 +02:00
|
|
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
|
|
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
|
|
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
|
|
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
|
|
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
2017-11-24 23:41:14 +01:00
|
|
|
|
|
|
|
void initPic(void)
|
|
|
|
{
|
2018-06-26 16:41:06 +02:00
|
|
|
/* Send CMD: Init + sequence in 4 DATA */
|
2018-07-13 13:48:43 +02:00
|
|
|
outb(PIC_MASTER_CMD, ICW1_INIT + ICW1_ICW4);
|
|
|
|
outb(PIC_SLAVE_CMD, ICW1_INIT + ICW1_ICW4);
|
2017-11-24 23:41:14 +01:00
|
|
|
|
|
|
|
/* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as
|
|
|
|
* intel
|
|
|
|
* reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */
|
2018-07-13 13:48:43 +02:00
|
|
|
outb(PIC_MASTER_DATA, IRQ_INTERRUPT_BASE_ADDRESS);
|
2018-07-13 14:14:14 +02:00
|
|
|
outb(PIC_SLAVE_DATA, IRQ_INTERRUPT_BASE_ADDRESS + 8);
|
2017-11-24 23:41:14 +01:00
|
|
|
|
|
|
|
/* Send ICW3 master: mask where slaves are connected */
|
2018-07-13 13:48:43 +02:00
|
|
|
outb(PIC_MASTER_DATA, 0x4);
|
2017-11-24 23:41:14 +01:00
|
|
|
/* Send ICW3 slave: index where the slave is connected on master */
|
2018-07-13 13:48:43 +02:00
|
|
|
outb(PIC_SLAVE_DATA, 0x2);
|
2017-11-24 23:41:14 +01:00
|
|
|
|
|
|
|
/* Send ICW4: 8086 mode, fully nested, not buffered, no implicit EOI */
|
2018-07-13 13:48:43 +02:00
|
|
|
outb(PIC_MASTER_DATA, ICW4_8086);
|
|
|
|
outb(PIC_SLAVE_DATA, ICW4_8086);
|
2017-11-24 23:41:14 +01:00
|
|
|
|
|
|
|
/* Send OCW1:
|
|
|
|
* Closing all IRQs : waiting for a correct handler The only IRQ
|
|
|
|
* enabled is the cascade (that's why we use 0xFB for the master) */
|
2018-07-13 13:48:43 +02:00
|
|
|
outb(PIC_MASTER_DATA, 0xFB);
|
|
|
|
outb(PIC_SLAVE_DATA, 0xFF);
|
2017-11-24 23:41:14 +01:00
|
|
|
}
|
|
|
|
|
2018-07-18 01:41:10 +02:00
|
|
|
void EOIIrq(int irq)
|
|
|
|
{
|
|
|
|
if (irq >= 8)
|
|
|
|
outb(PIC_SLAVE_CMD, PIC_EOI);
|
|
|
|
|
|
|
|
outb(PIC_MASTER_CMD, PIC_EOI);
|
|
|
|
}
|
|
|
|
|
2018-07-18 01:32:17 +02:00
|
|
|
void disableIrq(int irq)
|
2017-11-24 23:41:14 +01:00
|
|
|
{
|
|
|
|
if (irq < 8) {
|
|
|
|
uint8_t status = inb(PIC_MASTER_DATA);
|
2018-07-18 01:13:32 +02:00
|
|
|
outb(PIC_MASTER_DATA, (status | (1 << irq)));
|
2017-11-24 23:41:14 +01:00
|
|
|
} else {
|
|
|
|
uint8_t status = inb(PIC_SLAVE_DATA);
|
2018-07-18 01:28:27 +02:00
|
|
|
outb(PIC_SLAVE_DATA, (status | (1 << (irq - 8))));
|
2017-11-24 23:41:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-18 01:32:17 +02:00
|
|
|
void enableIrq(int irq)
|
2017-11-24 23:41:14 +01:00
|
|
|
{
|
|
|
|
if (irq < 8) {
|
|
|
|
uint8_t status = inb(PIC_MASTER_DATA);
|
2018-07-18 01:13:32 +02:00
|
|
|
outb(PIC_MASTER_DATA, (status & ~(1 << irq)));
|
2017-11-24 23:41:14 +01:00
|
|
|
} else {
|
|
|
|
uint8_t status = inb(PIC_SLAVE_DATA);
|
2018-07-18 01:28:27 +02:00
|
|
|
outb(PIC_SLAVE_DATA, (status & ~(1 << (irq - 8))));
|
2017-11-24 23:41:14 +01:00
|
|
|
}
|
|
|
|
}
|