Skip to content

Commit 1a98cab

Browse files
author
Carlos Fenollosa
committed
lesson 20, preliminar
1 parent c2a0593 commit 1a98cab

File tree

19 files changed

+1047
-6
lines changed

19 files changed

+1047
-6
lines changed

19-interrupts-irqs/README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
**Goal: Finish the interrupts implementation and CPU timer**
44

5-
Remap the PIC
6-
-------------
7-
85
When the CPU boots, the PIC maps IRQs 0-7 to INT 0x8-0xF
96
and IRQs 8-15 to INT 0x70-0x77. This conflicts with the ISRs
107
we programmed last lesson. Since we programmed ISRs 0-31,
@@ -14,7 +11,8 @@ The PICs are communicated with via I/O ports (see lesson 15).
1411
The Master PIC has command 0x20 and data 0x21, while the slave has
1512
command 0xA0 and data 0xA1.
1613

17-
The code for remapping the PICs is obfuscated, so check
14+
The code for remapping the PICs is weird and includes
15+
some masks, so check
1816
[this article](http://www.osdev.org/wiki/PIC) if you're curious.
1917
Otherwise, just look at `cpu/isr.c`, new code after we set the IDT
2018
gates for the ISRs. After that, we add the IDT gates for IRQs.
@@ -30,5 +28,10 @@ We then create this `irq_common_stub` which is very similar to the ISR one.
3028
It is located at the top of `interrupt.asm`, and it also defines
3129
a new `[extern irq_handler]`
3230

33-
Now back to C code.
34-
- Write the `irq_handler` in C:
31+
Now back to C code, to write the `irq_handler()` in `isr.c`. It sends some
32+
EOIs to the PICs and calls the appropriate handler, which is stored in an array
33+
named `interrupt_handlers` and defined at the top of the file. The new structs
34+
are defined in `isr.h`. We will also use a simple function to register
35+
the interrupt handlers.
36+
37+
That was a lot of work, but now we can define our first IRQ handler!

20-interrupts-timer/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../19-interrupts-irqs/Makefile

20-interrupts-timer/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
Everything is now ready to test our hardware interrupts.
3+
4+
Timer
5+
-----
6+
7+
The timer is easy to configure. First we'll declare an `init_timer()` on `cpu/timer.h` and
8+
implement it on `cpu/timer.c`. It is just a matter of computing the clock frequency and
9+
sending the bytes to the appropriate ports.
10+
11+
## se printa gibberish, pq? mirar primero si se arregla con un kprint_int
12+
## yo tenia una funcion que printaba enteros??!!! pero al rever. hacerla ahora bien y
13+
## en el proximo episodio limpiar codigo y crear una libc
14+
15+
16+
Finally, go back to the `kernel/kernel.c` and do two things. Enable interrupts again
17+
(very important!) and then initialize the timer interrupt.
18+
19+
Go `make run` and you'll see the clock ticking! Unfortunately we are not printing the correct values
20+
on screen, so we'll go ahead to `drivers/screen.c` and add a new `kprint_int()` method, also declaring
21+
it on `drivers/screen.h`

20-interrupts-timer/boot

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../19-interrupts-irqs/boot

20-interrupts-timer/cpu/idt.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "idt.h"
2+
#include "../kernel/util.h"
3+
4+
void set_idt_gate(int n, u32 handler) {
5+
idt[n].low_offset = low_16(handler);
6+
idt[n].sel = KERNEL_CS;
7+
idt[n].always0 = 0;
8+
idt[n].flags = 0x8E;
9+
idt[n].high_offset = high_16(handler);
10+
}
11+
12+
void set_idt() {
13+
idt_reg.base = (u32) &idt;
14+
idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
15+
/* Don't make the mistake of loading &idt -- always load &idt_reg */
16+
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
17+
}

20-interrupts-timer/cpu/idt.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef IDT_H
2+
#define IDT_H
3+
4+
#include "types.h"
5+
6+
/* Segment selectors */
7+
#define KERNEL_CS 0x08
8+
9+
/* How every interrupt gate (handler) is defined */
10+
typedef struct {
11+
u16 low_offset; /* Lower 16 bits of handler function address */
12+
u16 sel; /* Kernel segment selector */
13+
u8 always0;
14+
/* First byte
15+
* Bit 7: "Interrupt is present"
16+
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
17+
* Bit 4: Set to 0 for interrupt gates
18+
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
19+
u8 flags;
20+
u16 high_offset; /* Higher 16 bits of handler function address */
21+
} __attribute__((packed)) idt_gate_t ;
22+
23+
/* A pointer to the array of interrupt handlers.
24+
* Assembly instruction 'lidt' will read it */
25+
typedef struct {
26+
u16 limit;
27+
u32 base;
28+
} __attribute__((packed)) idt_register_t;
29+
30+
#define IDT_ENTRIES 256
31+
idt_gate_t idt[IDT_ENTRIES];
32+
idt_register_t idt_reg;
33+
34+
35+
/* Functions implemented in idt.c */
36+
void set_idt_gate(int n, u32 handler);
37+
void set_idt();
38+
39+
#endif

0 commit comments

Comments
 (0)