metal-cos/sys/amd64/ioapic.c
2014-07-18 15:09:52 -07:00

82 lines
1.6 KiB
C

/*
* IOAPIC
*/
#include <stdbool.h>
#include <stdint.h>
#include <kassert.h>
#include <cdefs.h>
#include "amd64.h"
#include "pmap.h"
#include "trap.h"
#define IOAPICBASE 0xFEC00000
#define IOAPICID 0x00 /* IOAPIC ID */
#define IOAPICVER 0x01 /* IOAPIC Version */
#define IOAPICARB 0x02 /* IOAPIC Arbitration ID */
#define IOREDTBL0 0x10
#define IOREDTBL23 0x3E
#define IOREDTBL_LEN 24
#define IOREDTBL_MASK 0x00010000
#define IOREDTBL_LOGICAL 0x00000800
uint32_t
IOAPIC_Read(uint32_t reg)
{
uint32_t volatile *addr = (uint32_t volatile *)DMPA2VA(IOAPICBASE);
uint32_t volatile *cmd = (uint32_t volatile *)DMPA2VA(IOAPICBASE + 0x10);
ASSERT(reg <= 0xFF);
*addr = reg;
return *cmd;
}
void
IOAPIC_Write(uint32_t reg, uint32_t val)
{
uint32_t volatile *addr = (uint32_t volatile *)DMPA2VA(IOAPICBASE);
uint32_t volatile *cmd = (uint32_t volatile *)DMPA2VA(IOAPICBASE + 0x10);
ASSERT(reg <= 0xFF);
*addr = reg;
*cmd = val;
}
void
IOAPIC_Init()
{
int i;
uint32_t id = (IOAPIC_Read(IOAPICID) >> 24) & 0x0F;
uint32_t maxInts = (IOAPIC_Read(IOAPICVER) >> 16) & 0xFF;
kprintf("IOAPIC: ID:%d Max Interrupts: %d\n", id, maxInts);
for (i = 0; i <= IOREDTBL_LEN; i++)
{
IOAPIC_Write(IOREDTBL0 + 2*i, IOREDTBL_MASK | (T_IRQ_BASE + i));
IOAPIC_Write(IOREDTBL0 + 2*i + 1, 0);
}
}
void
IOAPIC_Enable(int irq)
{
uint32_t val = IOAPIC_Read(IOREDTBL0 + 2*irq);
IOAPIC_Write(IOREDTBL0 + 2*irq, val & ~IOREDTBL_MASK);
}
void
IOAPIC_Disable(int irq)
{
uint32_t val = IOAPIC_Read(IOREDTBL0 + 2*irq);
IOAPIC_Write(IOREDTBL0 + 2*irq, val | IOREDTBL_MASK);
}