aboutsummaryrefslogtreecommitdiff
path: root/src/utils/pic.c
blob: 7681a13b436f99362123001ee393116064b2e13a (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "pic.h"
#include "asm.h"
#include "mem.h"
#include "syscall.h"

struct IDT_REGISTER IDTR={
    200*8,
    0x0
};

/// Bridge between IDT and functions call
asm (
".macro  SAVE_REGS        \n\t"
    "pushal               \n\t"
    "push %ds             \n\t"
    "push %es             \n\t"
    "push %fs             \n\t"
    "push %gs             \n\t"
    "push %ebx            \n\t"
    "mov $0x10,%bx        \n\t"
    "mov %bx,%ds          \n\t"
    "pop %ebx             \n\t"
".endm                    \n\t"
".macro  RESTORE_REGS     \n\t"
    "pop %gs              \n\t"
    "pop %fs              \n\t"
    "pop %es              \n\t"
    "pop %ds              \n\t"
    "popal                \n\t"
".endm                    \n\t"
"PIC_IRQ_DEFAULT:         \n\t"
    "SAVE_REGS            \n\t"
    "movb $0x20, %al      \n\t"
    "outb %al, $0x20      \n\t"
    "RESTORE_REGS         \n\t"
    "iret                 \n\t"
"PIC_IRQ_PRINT:           \n\t"
    "SAVE_REGS            \n\t"
    "call _8042_keypress  \n\t"
    "movb $0x20, %al      \n\t"
    "outb %al, $0x20      \n\t"
    "RESTORE_REGS         \n\t"
    "iret                 \n\t"
"PIC_IRQ_CLOCK:           \n\t"
    "SAVE_REGS            \n\t"
    "call clock           \n\t"
    "movb $0x20, %al      \n\t"
    "outb %al, $0x20      \n\t"
    "RESTORE_REGS         \n\t"
    "iret                 \n\t"
"PIC_IRQ_SYSCALL:         \n\t"
    "SAVE_REGS            \n\t"
    "call syscall         \n\t"
    "movb $0x20, %al      \n\t"
    "outb %al, $0x20      \n\t"
    "RESTORE_REGS         \n\t"
    "iret                 \n\t"
);

extern u32 PIC_IRQ_DEFAULT,PIC_IRQ_PRINT,PIC_IRQ_CLOCK, PIC_IRQ_SYSCALL;

void pic_enable_interrupt(){
    // Map first default 32 entries 
    for(int i=0;i<200;i++){
        pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_DEFAULT,IDT_INT_GATE},i);
        if(i==32)
            pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_CLOCK,IDT_INT_GATE},i);
        if(i==33)
            pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_PRINT,IDT_INT_GATE},i);
        if(i==48)
            pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_SYSCALL,IDT_TRAP_GATE},i);
    }

    // Now configure 8952A

    // ICW1: Initialisation
    outbj(0x20,0x11); // Master
    outbj(0xA0,0x11); // Slave

    // ICW2: Map IRQ index to entry into the IDT
    outbj(0x21,0x20); // Start interrupt at offset 0x20 in IDT (index 32)
    outbj(0xA1,0x70); // Start interrupt at offset 0x50 in IDT (index 80)

    // ICW3: Indicate the connection between master and slave
    outbj(0x21,0x02); // Slave connected to pin 2
    outbj(0xA1,0x01); // Indicate pin id to the slave (2-1)

    // ICW4: Operating mode
    outbj(0x21,0x01); // Default operating mode
    outbj(0xA1,0x01); // Default operating mode

    // OCW: Masking
    outbj(0x21,0b11111100);


    asm("lidtl (IDTR)");
    asm("sti");
}

void pic_add_idt_entry(IDT_ENTRY entry, int id){
    int descriptor[2];
    descriptor[0]=entry.offset & 0xFFFF | entry.segment << 16;
    descriptor[1]=entry.type & 0xFFFF | entry.offset & 0xFFFF0000;
    memcpy((void*)descriptor, (void *)(IDTR.base+(id*8)),8);
}