aboutsummaryrefslogtreecommitdiff
path: root/src/core/apic.cc
blob: aba801a9dc32c930dd5f2a76ecc73a9afcb3f330 (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
#include "apic.hpp"

#include "paging.hpp"
#include "types.hpp"
#include "asm.hpp"
#include "libs/stdio.hpp"

#define APIC_LAPIC_ADDR 0xFEE00000
#define APIC_IOAPIC_ADDR 0xFEC00000
#define APIC_LAPIC_REG_SPURIOUS 0xF0
#define APIC_LAPIC_TIMER_LVT 0x320
#define APIC_LAPIC_TIMER_IC 0x380
#define APIC_LAPIC_TIMER_DVD 0x3E0
#define APIC_PRIOR 0x80
#define APIC_DFR 0xE0
#define APIC_EOI 0xB0

u8 lapic_space[4096] __attribute__((aligned(4096)));
u8 ioapic_space[4096] __attribute__((aligned(4096)));
char enable=0;
void apic_enable(){
    // Memory Allocation
    PAGE_MAP(lapic_space,APIC_LAPIC_ADDR, PAGING_OPT_PCD|PAGING_OPT_DEFAULTS);
    PAGE_MAP(ioapic_space,APIC_IOAPIC_ADDR,PAGING_OPT_PCD|PAGING_OPT_DEFAULTS);
    
    // Configure APIC register location and enable it via MSR
   /* u64 lapic_addr=(u64)APIC_LAPIC_ADDR;
    u32 high=lapic_addr>>32;
    u32 low=((u64)APIC_LAPIC_ADDR&0xFFFFFFFF);
    low|=0x800; // Enable apic
    WRITE_MSR(0x1B,high,low);*/
    
    // Configure LAPIC device using mmap
    apic_write(APIC_LAPIC_REG_SPURIOUS, 0x100&apic_read(APIC_LAPIC_REG_SPURIOUS));
    //apic_write(APIC_DFR, 0xFFFFFFFF);
   // apic_write(APIC_PRIOR, 0);
    apic_write(APIC_LAPIC_TIMER_DVD, 1);
    apic_write(APIC_LAPIC_TIMER_LVT, (1<<17)|61);
    apic_write(APIC_LAPIC_TIMER_IC, 100000);

    // Configure I/O APIC
    u32 *ioapic_reg=(u32*)ioapic_space;
    *ioapic_reg=0x12; // Select the 0x12 IRQ 
    ioapic_reg=(u32*)(((u64)ioapic_space)+0x10); // Now use the IOREGWIN to write
    *ioapic_reg=(0x0<<12)|60; // Enable IRQ 1 (0x12) and assign it to the vector 0x3C (index 60 in the IDT)
    enable=1;
}

void apic_write(u32 reg, u32 value){
    u32 *lapic_reg=(u32*)(lapic_space+reg);
    *lapic_reg=value;
}

u32 apic_read(u32 reg){
    u32 *lapic_reg=(u32*)(lapic_space+reg);
    return *lapic_reg;
}

extern "C" void apic_ack(){
    if(enable){
/*         u8 data;
        do {
            inb(0x64,data);
        }
        while((data&0x01) == 0);
        inb(0x60,data); */
        
        apic_write(APIC_EOI, 0);
    }
}