2006-08-04 20:12:31 +02:00
|
|
|
#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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2006-09-06 19:04:06 +02:00
|
|
|
#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
|
|
|
|
#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1)
|
2006-08-04 20:12:31 +02:00
|
|
|
|
|
|
|
static uint
|
|
|
|
ioapic_read(struct ioapic *io, int reg)
|
|
|
|
{
|
|
|
|
io->ioregsel = reg;
|
2006-09-06 19:27:19 +02:00
|
|
|
return io->iowin;
|
2006-08-04 20:12:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2006-09-08 17:14:43 +02:00
|
|
|
if(!ismp)
|
2006-09-08 17:07:45 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
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);
|
2006-08-04 20:12:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-08-08 21:58:06 +02:00
|
|
|
ioapic_enable (int irq, int cpunum)
|
2006-08-04 20:12:31 +02:00
|
|
|
{
|
|
|
|
uint l, h;
|
|
|
|
struct ioapic *io;
|
2006-09-07 03:37:58 +02:00
|
|
|
|
2006-09-08 17:14:43 +02:00
|
|
|
if(!ismp)
|
2006-09-08 17:07:45 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
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);
|
2006-08-04 20:12:31 +02:00
|
|
|
}
|