aboutsummaryrefslogtreecommitdiff
path: root/devices/pic_8259.c
blob: 75a2d0e1aef381e7146cf87e0bf126ebaeaf57e6 (plain)
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
#include "pic.h"
#include <sys/control.h>
#include <sys/io.h>

#define PIC1 0x20
#define PIC2 0xa0
#define DATA 1

// initialization
#define ICW1_INIT 0x10
// TODO
#define ICW1_ICW4 0x01
// 8086/88 mode
#define ICW4_8086 0x01

void
pic_init()
{
  outb(ICW1_INIT | ICW1_ICW4, PIC1);
  outb(ICW1_INIT | ICW1_ICW4, PIC2);

  outb(0x20, PIC1 + DATA); // offset 0x20
  outb(0x28, PIC2 + DATA); // offset 0x28

  outb(0x04, PIC1 + DATA); // tell master pic there is a slave pic
  outb(0x02, PIC2 + DATA); // tell slave pic its cascade identity

  outb(ICW4_8086, PIC1 + DATA);
  outb(ICW4_8086, PIC2 + DATA);

  // PIC masks
  outb(0xff, PIC1 + DATA);
  outb(0xff, PIC2 + DATA);
}

void
pic_enable()
{
  unsigned char mask1 = 0xff;
  mask1 &= ~(1 << 0); // irq0 timer
  mask1 &= ~(1 << 1); // irq1 keyboard
  mask1 &= ~(1 << 2); // irq1 cascade
  outb(mask1, PIC1 + DATA);

  unsigned char mask2 = 0xff;
  mask2 &= ~(1 << 4); // irq12 mouse
  outb(mask2, PIC2 + DATA);

  enable_interrupts();
}

void
pic_clear(unsigned char irq)
{
  outb(0x20, PIC1);
  if (irq >= 8) outb(0x20, PIC2);
}