Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / arch / x86_64 / irq.c
blobef92ebbe6de540b13bb1e3737483c89e08b402e4
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 <arch/io.h>
22 #include <string.h>
24 /* These are own ISRs that point to our special IRQ handler
25 * instead of the regular 'fault_handler' function */
26 extern void irq0();
27 extern void irq1();
28 extern void irq2();
29 extern void irq3();
30 extern void irq4();
31 extern void irq5();
32 extern void irq6();
33 extern void irq7();
34 extern void irq8();
35 extern void irq9();
36 extern void irq10();
37 extern void irq11();
38 extern void irq12();
39 extern void irq13();
40 extern void irq14();
41 extern void irq15();
43 /* This array is actually an array of function pointers. We use
44 * this to handle custom IRQ handlers for a given IRQ */
45 void *irq_routines[16] =
47 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0
51 /* This installs a custom IRQ handler for the given IRQ */
52 void irq_install_handler (int irq, void (*handler)(struct regs *r))
54 irq_routines[irq] = handler;
57 /* This clears the handler for a given IRQ */
58 void irq_uninstall_handler (int irq)
60 irq_routines[irq] = 0;
63 /* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This
64 * is a problem in protected mode, because IDT entry 8 is a
65 * Double Fault! Without remapping, every time IRQ0 fires,
66 * you get a Double Fault Exception, which is NOT actually
67 * what's happening. We send commands to the Programmable
68 * Interrupt Controller (PICs - also called the 8259's) in
69 * order to make IRQ0 to 15 be remapped to IDT entries 32 to
70 * 47 */
71 void irq_remap (void)
73 outb (0x20, 0x11);
74 outb (0xA0, 0x11);
75 outb (0x21, 0x20);
76 outb (0xA1, 0x28);
77 outb (0x21, 0x04);
78 outb (0xA1, 0x02);
79 outb (0x21, 0x01);
80 outb (0xA1, 0x01);
81 outb (0x21, 0x0);
82 outb (0xA1, 0x0);
85 /* We first remap the interrupt controllers, and then we install
86 * the appropriate ISRs to the correct entries in the IDT. This
87 * is just like installing the exception handlers */
88 unsigned int irq_install ()
90 irq_remap ();
92 idt_set_gate (32, (unsigned)irq0, 0x08, 0x8E);
93 idt_set_gate (33, (unsigned)irq1, 0x08, 0x8E);
94 idt_set_gate (34, (unsigned)irq2, 0x08, 0x8E);
95 idt_set_gate (35, (unsigned)irq3, 0x08, 0x8E);
96 idt_set_gate (36, (unsigned)irq4, 0x08, 0x8E);
97 idt_set_gate (37, (unsigned)irq5, 0x08, 0x8E);
98 idt_set_gate (38, (unsigned)irq6, 0x08, 0x8E);
99 idt_set_gate (39, (unsigned)irq7, 0x08, 0x8E);
101 idt_set_gate (40, (unsigned)irq8, 0x08, 0x8E);
102 idt_set_gate (41, (unsigned)irq9, 0x08, 0x8E);
103 idt_set_gate (42, (unsigned)irq10, 0x08, 0x8E);
104 idt_set_gate (43, (unsigned)irq11, 0x08, 0x8E);
105 idt_set_gate (44, (unsigned)irq12, 0x08, 0x8E);
106 idt_set_gate (45, (unsigned)irq13, 0x08, 0x8E);
107 idt_set_gate (46, (unsigned)irq14, 0x08, 0x8E);
108 idt_set_gate (47, (unsigned)irq15, 0x08, 0x8E);
110 return 1;
113 /* Each of the IRQ ISRs point to this function, rather than
114 * the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
115 * to be told when you are done servicing them, so you need
116 * to send them an "End of Interrupt" command (0x20). There
117 * are two 8259 chips: The first exists at 0x20, the second
118 * exists at 0xA0. If the second controller (an IRQ from 8 to
119 * 15) gets an interrupt, you need to acknowledge the
120 * interrupt at BOTH controllers, otherwise, you only send
121 * an EOI command to the first controller. If you don't send
122 * an EOI, you won't raise any more IRQs */
123 void irq_handler (struct regs *r)
125 /* This is a blank function pointer */
126 void (*handler) (struct regs *r);
128 /* Find out if we have a custom handler to run for this
129 * IRQ, and then finally, run it */
130 handler = irq_routines[r->int_no - 32];
132 if (handler)
133 handler (r);
135 /* If the IDT entry that was invoked was greater than 40
136 * (meaning IRQ8 - 15), then we need to send an EOI to
137 * the slave controller */
138 if (r->int_no >= 40)
139 outb (0xA0, 0x20);
141 /* In either case, we need to send an EOI to the master
142 * interrupt controller too */
143 outb (0x20, 0x20);