diff --git a/kernel/pic.c b/kernel/pic.c new file mode 100644 index 0000000..e494170 --- /dev/null +++ b/kernel/pic.c @@ -0,0 +1,75 @@ +/* +Copyright (C) 2015-2019 The University of Notre Dame +This software is distributed under the GNU General Public License. +See the file LICENSE for details. +*/ + +#include "ioports.h" +#include "kernel/types.h" +#include "console.h" + +#define PIC_ICW1 0x11 +#define PIC_ICW4_MASTER 0x01 +#define PIC_ICW4_SLAVE 0x05 +#define PIC_ACK_SPECIFIC 0x60 + +static uint8_t pic_control[2] = { 0x20, 0xa0 }; +static uint8_t pic_data[2] = { 0x21, 0xa1 }; + +void pic_init(int pic0base, int pic1base) +{ + outb(PIC_ICW1, pic_control[0]); + outb(pic0base, pic_data[0]); + outb(1 << 2, pic_data[0]); + outb(PIC_ICW4_MASTER, pic_data[0]); + outb(~(1 << 2), pic_data[0]); + + outb(PIC_ICW1, pic_control[1]); + outb(pic1base, pic_data[1]); + outb(2, pic_data[1]); + outb(PIC_ICW4_SLAVE, pic_data[1]); + outb(~0, pic_data[1]); + + printf("pic: ready\n"); +} + +void pic_enable(uint8_t irq) +{ + uint8_t mask; + if(irq < 8) { + mask = inb(pic_data[0]); + mask = mask & ~(1 << irq); + outb(mask, pic_data[0]); + } else { + irq -= 8; + mask = inb(pic_data[1]); + mask = mask & ~(1 << irq); + outb(mask, pic_data[1]); + pic_enable(2); + } +} + +void pic_disable(uint8_t irq) +{ + uint8_t mask; + if(irq < 8) { + mask = inb(pic_data[0]); + mask = mask | (1 << irq); + outb(mask, pic_data[0]); + } else { + irq -= 8; + mask = inb(pic_data[1]); + mask = mask | (1 << irq); + outb(mask, pic_data[1]); + } +} + +void pic_acknowledge(uint8_t irq) +{ + if(irq >= 8) { + outb(PIC_ACK_SPECIFIC + (irq - 8), pic_control[1]); + outb(PIC_ACK_SPECIFIC + (2), pic_control[0]); + } else { + outb(PIC_ACK_SPECIFIC + irq, pic_control[0]); + } +}