summaryrefslogtreecommitdiff
path: root/ioapic.c
blob: 8745a69e46fd3e4f38229d1f937e13e6c0f7c9e8 (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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "types.h"
#include "mp.h"
#include "defs.h"
#include "x86.h"
#include "traps.h"
#include "ioapic.h"

struct ioapic {
  uint ioregsel;  uint p01; uint p02; uint p03;
  uint iowin;     uint p11; uint p12; uint p13;
};


#define IOAPIC_REDTBL_LO(i)  (IOAPIC_REDTBL + (i) * 2)
#define IOAPIC_REDTBL_HI(i)  (IOAPIC_REDTBL_LO(i) + 1)

static uint
ioapic_read(struct ioapic *io, int reg)
{
  io->ioregsel = reg;
  return io->iowin;
}

static void
ioapic_write(struct ioapic *io, int reg, uint val)
{
  io->ioregsel = reg;
  io->iowin = val;
}

void
ioapic_init(void)
{
  struct ioapic *io;
  uint l, h;
  int nintr;
  uchar id;
  int i;

  if (ismp) {
    io = (struct ioapic*) IO_APIC_BASE;
    l = ioapic_read(io, IOAPIC_VER);
    nintr =  ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
    id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
    if(id != ioapic_id)
      cprintf("ioapic_init: id isn't equal to ioapic_id; not a MP\n");
    for(i = 0; i < nintr; i++) {
      // active-hi and edge-triggered for ISA interrupts
      // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
      // Assume that pins 1-15 are ISA interrupts
      l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
      l = l & ~IOART_INTMASK;  // allow INTs
      l |= IOART_INTMSET;
      l = l & ~IOART_INTPOL;   // active hi
      l = l & ~IOART_TRGRMOD;  // edgee triggered
      l = l & ~IOART_DELMOD;   // fixed
      l = l & ~IOART_DESTMOD;  // physical mode
      l = l | (IRQ_OFFSET + i); // vector
      ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
      h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
      h &= ~IOART_DEST;
      ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
    }
  }
}

void
ioapic_enable (int irq, int cpunum)
{
  uint l, h;
  struct ioapic *io;
  
  if (ismp) {
    io = (struct ioapic*) IO_APIC_BASE;
    l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
    l = l & ~IOART_INTMASK;  // allow INTs
    ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
    h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
    h &= ~IOART_DEST;
    h |= (cpunum << APIC_ID_SHIFT);
    ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
  }
}