Started setting up threads for user-space execution.
[marionette.git] / kernel / interrupt.c
blob617055099c7f7fed45313c7cd4992eff30cf852c
1 /*
2 * Copyright (c) 2008 Joshua Phillips. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "interrupt.h"
29 #include "gdt.h"
30 #include "console.h"
31 #include "portio.h"
33 /* PIC registers */
34 #define PIC1_CMD 0x20
35 #define PIC1_DATA 0x21
36 #define PIC2_CMD 0xA0
37 #define PIC2_DATA 0xA1
39 /* PIC commands */
40 #define PIC_ACK 0x20
41 #define ICW1_ICW4 0x01
42 #define ICW1_SINGLE 0x02
43 #define ICW1_INTERVAL4 0x04
44 #define ICW1_LEVEL 0x08
45 #define ICW1_INIT 0x10
46 #define ICW4_8086 0x01
47 #define ICW4_AUTO 0x02
48 #define ICW4_BUF_SLAVE 0x08
49 #define ICW4_BUF_MASTER 0x0C
50 #define ICW4_SFNM 0x10
52 isr_t interrupt_handlers[256];
54 void isr0(void);
55 void isr1(void);
57 static void default_interrupt_handler(int vector, struct interrupt_stack *is)
59 console_printf(&tty1, "Interrupt 0x%X fired.\n", vector);
60 console_printf(&tty1, "Return address: 0x%.8X\n", is->eip);
61 if (vector >= 0x20 && vector < 0x30)
62 ack_irq(vector - 0x20);
65 static void load_idt_addr(unsigned short *idt)
67 asm volatile (
68 "subl $6,%%esp \n"
69 "movw %%cx,(%%esp) \n"
70 "movl %%eax,2(%%esp) \n"
71 "lidt (%%esp) \n"
72 "addl $6,%%esp \n"
73 :: "c" (256 * 8), "a" (idt)
74 : "cc");
77 static void io_wait(void)
79 int i;
80 for (i=0; i<16; i++)
81 outb(0x80, 0x00);
84 static void remap_pics(void)
86 int pic1_offset = 0x20;
87 int pic2_offset = 0x28;
88 unsigned char a1, a2;
90 //a1 = inb(PIC1_DATA);
91 //a2 = inb(PIC2_DATA);
92 a1 = 0xFF;
93 a2 = 0xFF;
95 outb(PIC1_CMD, ICW1_INIT + ICW1_ICW4);
96 io_wait();
97 outb(PIC2_CMD, ICW1_INIT + ICW1_ICW4);
98 io_wait();
99 outb(PIC1_DATA, pic1_offset);
100 io_wait();
101 outb(PIC2_DATA, pic2_offset);
102 io_wait();
103 outb(PIC1_DATA, 4);
104 io_wait();
105 outb(PIC2_DATA, 2);
106 io_wait();
107 outb(PIC1_DATA, ICW4_8086);
108 io_wait();
109 outb(PIC2_DATA, ICW4_8086);
110 io_wait();
111 outb(PIC1_DATA, a1);
112 outb(PIC2_DATA, a2);
115 void interrupt_init(void **p_idt)
117 int i, isr_size;
118 unsigned long p;
119 uint16_t *idt = (uint16_t *) *p_idt;
120 *p_idt = idt + (256 * 4);
122 isr_size = (unsigned long) isr1 - (unsigned long) isr0;
123 p = (unsigned long) isr0;
125 // fill in the IDT
126 for (i=0; i<256; i++){
127 idt[i * 4 + 0] = p;
128 idt[i * 4 + 1] = SEG_DPL0_CODE;
129 idt[i * 4 + 2] = 0x8E00;
130 idt[i * 4 + 3] = p >> 16;
131 p += isr_size;
133 // set the default interrupt handler, too
134 interrupt_handlers[i] = default_interrupt_handler;
137 idt[0x80 * 4 + 2] |= (3 << 13);
139 // load the IDT address
140 load_idt_addr(idt);
142 // remap the PICs
143 remap_pics();
145 // Enable the cascade irq (so that the slave PIC can work)
146 unmask_irq(2);
149 void enable_interrupts(void)
151 asm volatile ("sti");
154 void disable_interrupts(void)
156 asm volatile ("cli");
159 void set_interrupt(int vector, isr_t handler)
161 interrupt_handlers[vector] = handler;
164 void clear_interrupt(int vector)
166 interrupt_handlers[vector] = default_interrupt_handler;
169 int irq_to_int(int irq)
171 return irq + 0x20;
174 int int_to_irq(int intn)
176 return intn - 0x20;
179 void unmask_irq(int n)
181 unsigned char a;
182 if (n < 8){
183 // master PIC
184 a = inb(PIC1_DATA);
185 a &= ~(1 << n);
186 outb(PIC1_DATA, a);
187 } else {
188 // slave PIC
189 a = inb(PIC2_DATA);
190 a &= ~(1 << (n - 8));
191 outb(PIC2_DATA, a);
195 void mask_irq(int n)
197 unsigned char a;
198 if (n < 8){
199 // master PIC
200 a = inb(PIC1_DATA);
201 a |= (1 << n);
202 outb(PIC1_DATA, a);
203 } else {
204 // slave PIC
205 a = inb(PIC2_DATA);
206 a |= (1 << (n - 8));
207 outb(PIC2_DATA, a);
211 void ack_irq(int n)
213 if (n >= 8)
214 outb(PIC2_CMD, PIC_ACK);
215 outb(PIC1_CMD, PIC_ACK);