xv6/ioapic.c
2006-09-08 15:14:43 +00:00

85 lines
2 KiB
C

#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)
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);
}
}
void
ioapic_enable (int irq, int cpunum)
{
uint l, h;
struct ioapic *io;
if(!ismp)
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);
}