kernel/pic.c (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
#include "cedos/pic.h"
#include "assembly.h"
#include "common.h"
/*!
* Moves irqs to appropriate addresses and enables all PIC interrupts
* \return 1 on success, 0 on fail
*/
volatile int pic_init(void) {
// start initialization sequence
outb(0x11, PIC1_COMMAND);
outb(0x11, PIC2_COMMAND);
nop(); nop(); nop(); nop();
// set offsets
outb(PIC1_OFFSET, PIC1_DATA);
outb(PIC2_OFFSET, PIC2_DATA);
nop(); nop(); nop(); nop();
// set wiring info
outb(0b00000100, PIC1_DATA);
outb(0b00000010, PIC2_DATA);
nop(); nop(); nop(); nop();
// set operating mode (8086)
outb(0x01, PIC1_DATA);
outb(0x01, PIC2_DATA);
nop(); nop(); nop(); nop();
// clear interrupt masks
outb(0xff, PIC1_DATA);
outb(0xff, PIC2_DATA);
}
/*!
* Unmasks interrupt number \p irq.
* \param irq Number of the interrupt to unmask.
* \return 1 on success, 0 on fail
*/
int pic_unmask_interrupt(int irq) {
uint16_t port;
if (irq >= 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
irq -= 8;
}
uint8_t mask = inb(port);
mask &= ~(1 << irq);
outb(mask, port);
}
/*!
* Masks interrupt number \p irq.
* \param irq Number of the interrupt to mask.
* \return 1 on success, 0 on fail
*/
int pic_mask_interrupt(int irq) {
uint16_t port;
if (irq >= 8) {
port = PIC1_DATA;
} else {
port = PIC2_DATA;
irq -= 8;
}
uint8_t mask = inb(port);
mask |= 1 << irq;
outb(mask, port);
}