summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-05-31 21:50:11 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-05-31 21:50:11 +0200
commit8e2b19ccd934a4ff8f41ef3fe833381c71f550f8 (patch)
tree4f7184f8fe5dd20781b96730f53cf2021f90eb25
parentc1c2b3082caeed8f7c1dfa9d7e303d650e2650b3 (diff)
downloadabaos-8e2b19ccd934a4ff8f41ef3fe833381c71f550f8.tar.gz
abaos-8e2b19ccd934a4ff8f41ef3fe833381c71f550f8.tar.bz2
interrupt separation between CPU exceptions and hardware IRQs by the PIC,
started to program the PICs for interrupt delivery
-rw-r--r--doc/LINKS.TODO3
-rw-r--r--src/interrupts.asm18
-rw-r--r--src/interrupts.c38
-rw-r--r--src/interrupts.h7
-rw-r--r--src/kernel.c32
5 files changed, 72 insertions, 26 deletions
diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO
index 15ea245..a7b3f15 100644
--- a/doc/LINKS.TODO
+++ b/doc/LINKS.TODO
@@ -37,3 +37,6 @@ longjmp:
http://blog.reverberate.org/2013/05/deep-wizardry-stack-unwinding.html
http://prettyos.de
+PIC:
+http://www.brokenthorn.com/Resources/OSDevPic.html
+
diff --git a/src/interrupts.asm b/src/interrupts.asm
index c21229c..9a05883 100644
--- a/src/interrupts.asm
+++ b/src/interrupts.asm
@@ -37,13 +37,27 @@ interrupts_ignore_request:
; void interrupts_handle_request_0x00( );
%macro exception_stub 1
-global interrupts_handle_request_%1
-interrupts_handle_request_%1:
+global interrupts_handle_exception_%1
+interrupts_handle_exception_%1:
mov [interrupt_no], byte %1
+ jmp int_entry
%endmacro
exception_stub 0x00
+; IRQs and exceptions would normally collidate, that's why the
+; hardware interrupts must be transposed by an offset
+IRQ_BASE equ 0x20
+
+%macro irq_stub 1
+global interrupts_handle_irq_%1
+interrupts_handle_irq_%1:
+ mov [interrupt_no], byte IRQ_BASE + %1
+ jmp int_entry
+%endmacro
+
+irq_stub 0x00
+
int_entry:
; safe state of interrupted code
pusha
diff --git a/src/interrupts.c b/src/interrupts.c
index 810f105..59f38b8 100644
--- a/src/interrupts.c
+++ b/src/interrupts.c
@@ -17,6 +17,16 @@
// types of IDT entries
#define IDT_TYPE_INTERRUPT_GATE 0xE
+// offset for hardware interrupts
+#define IRQ_BASE 0x20
+#define IRQ_BASE_MASTER IRQ_BASE
+#define IRQ_BASE_SLAVE IRQ_BASE_MASTER + 8
+
+// PIC constants
+
+#define ICW1_ICW4 0x01 // support a 4th initialization word (ICW4)
+#define ICW1_INIT 0x10 // bit indicating initialization of chip
+
void interrupts_init( interrupt_t *interrupt )
{
memset( interrupt, 0, sizeof( interrupt_t ) );
@@ -28,16 +38,34 @@ void interrupts_init( interrupt_t *interrupt )
// divide-by-zero exception 0x00
interrupts_register_interrupt( interrupt, 0x00, GDT_CODE_SEGMENT_SELECTOR,
- &interrupts_handle_request_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE );
+ &interrupts_handle_exception_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE );
- interrupt->idt_pointer.size = 256 * sizeof( interrupt_gate_descriptor_t ) - 1;
- interrupt->idt_pointer.base = (uint32_t)interrupt->descriptor_table;
-
- interrupts_load_idt( &interrupt->idt_pointer );
+ // IRQ 0 - PIT - programmable interrupt timer
+ interrupts_register_interrupt( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR,
+ &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE );
+ // IRQ 1 - keyboard
+ interrupts_register_interrupt( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR,
+ &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE );
+
port8_init( &interrupt->PIC_master_control, 0x20 );
port8_init( &interrupt->PIC_master_data, 0x21 );
+ port8_init( &interrupt->PIC_slave_control, 0xA0 );
+ port8_init( &interrupt->PIC_slave_data, 0xA1 );
+
+ // initialize hardware management PICs (ICW1)
+ port8_write( &interrupt->PIC_master_control, ICW1_ICW4 | ICW1_INIT );
+ port8_write( &interrupt->PIC_slave_control, ICW1_ICW4 | ICW1_INIT );
+ // set IRQ base of both PICS (ICW2)
+ port8_write( &interrupt->PIC_master_data, IRQ_BASE_MASTER );
+ port8_write( &interrupt->PIC_slave_data, IRQ_BASE_SLAVE );
+
+ // tell CPU where the IDT is
+ interrupt->idt_pointer.size = 256 * sizeof( interrupt_gate_descriptor_t ) - 1;
+ interrupt->idt_pointer.base = (uint32_t)interrupt->descriptor_table;
+
+ interrupts_load_idt( &interrupt->idt_pointer );
}
void interrupts_register_interrupt( interrupt_t *interrupts,
diff --git a/src/interrupts.h b/src/interrupts.h
index 593a993..e90506f 100644
--- a/src/interrupts.h
+++ b/src/interrupts.h
@@ -46,6 +46,10 @@ typedef struct {
interrupt_gate_descriptor_t descriptor_table[NOF_INTERRUPT_GATES];
port8_t PIC_master_control;
port8_t PIC_master_data;
+ // since PC/AT we always have a slave PIC, we don't support the PC/XT architecture
+ // with just one PIC
+ port8_t PIC_slave_control;
+ port8_t PIC_slave_data;
} interrupt_t;
void interrupts_enable( void );
@@ -59,7 +63,8 @@ void interrupts_load_idt( interrupt_descriptor_table_pointer_t *idt_pointer );
uint32_t interrupts_handle_interrupt( uint8_t interrupt_no, uint32_t esp );
void interrupts_ignore_request( );
-void interrupts_handle_request_0x00( );
+void interrupts_handle_exception_0x00( );
+void interrupts_handle_irq_0x00( );
// initialize IDT
// handle gates
diff --git a/src/kernel.c b/src/kernel.c
index 355067a..e33d509 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -11,22 +11,17 @@
static jmp_buf panic_jmp_buf;
-static vga_t vga;
-static console_t console;
-// static serial_t serial;
-
void entry( void )
{
+ serial_t serial;
+ serial_init( &serial );
-// serial_t serial;
-// serial_init( &serial );
-
-// vga_t vga;
+ vga_t vga;
vga_init( &vga );
vga_set_color( &vga, VGA_COLOR_LIGHT_GREY );
vga_set_background_color( &vga, VGA_COLOR_BLACK );
-// console_t console;
+ console_t console;
console_init( &console );
console_add_vga_output( &console, &vga );
// console_add_serial_output( &console, &serial );
@@ -39,17 +34,18 @@ void entry( void )
puts( "Initializing interrupts" );
interrupt_t interrupt;
interrupts_init( &interrupt );
- interrupts_enable( );
-
-//~ vga_put_char_at( &vga, 81, 20, 'X' );
// exit point in case of kernel panic, do this as soon as
// possible
- int v = setjmp( panic_jmp_buf );
- printf( "setjmp returned %d\n", v );
- if( v > 0 ) {
+ if( setjmp( panic_jmp_buf ) > 0 ) {
goto TERMINATE;
}
+
+ // TODO: initialize hardware here
+
+ interrupts_enable( );
+
+//~ vga_put_char_at( &vga, 81, 20, 'X' );
console_put_string( &console, "Running.." );
@@ -62,9 +58,9 @@ void entry( void )
vga_put_char_at( &vga, x_pos, y_pos, '.' );
x_pos++;
// serial_put_char( &serial, '.' );
-int y = 0;
-int x = 12 / y;
-printf( "Hex number is 0x%X and string is '%s'\n", x, "abaos" );
+//~ int y = 0;
+//~ int x = 12 / y;
+//~ printf( "Hex number is 0x%X and string is '%s'\n", x, "abaos" );
}
vga_put_char_at( &vga, x_pos, y_pos, bar[i%4] );