New developer version 0.6.8; added select () function; added demonstrating example...
[ZeXOS.git] / kernel / arch / x86_64 / idt.c
blob04a1d7af4276e6ec9d76e331e6c8451745c7f8a8
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <system.h>
21 #include <build.h>
22 #include <arch/io.h>
23 #include <string.h>
25 /* Defines an IDT entry */
26 struct idt_entry
28 unsigned short base_lo;
29 unsigned short sel;
30 unsigned char always0;
31 unsigned char flags;
32 unsigned short base_hi;
33 } __attribute__((packed));
35 struct idt_ptr
37 unsigned short limit;
38 unsigned int base;
39 } __attribute__((packed));
41 /* Declare an IDT of 256 entries. Although we will only use the
42 * first 32 entries in this tutorial, the rest exists as a bit
43 * of a trap. If any undefined IDT entry is hit, it normally
44 * will cause an "Unhandled Interrupt" exception. Any descriptor
45 * for which the 'presence' bit is cleared (0) will generate an
46 * "Unhandled Interrupt" exception */
47 struct idt_entry idt[256];
48 struct idt_ptr idtp;
50 /* This exists in 'start.asm', and is used to load our IDT */
51 extern void idt_load();
53 #define set_intr_gate(n,addr) \
54 _set_gate(&idt[n],14,0,addr)
56 #define set_trap_gate(n,addr) \
57 _set_gate(&idt[n],15,0,addr)
59 #define set_system_gate(n,addr) \
60 _set_gate(&idt[n],15,3,addr)
62 /* Use this function to set an entry in the IDT. Alot simpler
63 * than twiddling with the GDT ;) */
64 void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
66 /* The interrupt routine's base address */
67 idt[num].base_lo = (base & 0xFFFF);
68 idt[num].base_hi = (base >> 16) & 0xFFFF;
70 /* The segment or 'selector' that this IDT entry will use
71 * is set here, along with any access flags */
72 idt[num].sel = sel;
73 idt[num].always0 = 0;
74 idt[num].flags = flags;
77 extern int system_call (void);
79 /* Installs the IDT */
80 unsigned int idt_install ()
82 /* Sets the special IDT pointer up, just like in 'gdt.c' */
83 idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
84 idtp.base = &idt;
86 /* Clear out the entire IDT, initializing it to zeros */
87 memset(&idt, 0, sizeof(struct idt_entry) * 256);
89 /* Add any new ISRs to the IDT here using idt_set_gate */
91 /* Points the processor's internal register to the new IDT */
92 idt_load ();
94 set_system_gate (0x80, &system_call);
96 return 1;