basekernel/kernel/pic.c

76 lines
1.5 KiB
C

/*
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]);
}
}