summaryrefslogtreecommitdiff
path: root/src/hardware/interrupts.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/hardware/interrupts.h')
-rw-r--r--src/hardware/interrupts.h103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/hardware/interrupts.h b/src/hardware/interrupts.h
new file mode 100644
index 0000000..8ab485e
--- /dev/null
+++ b/src/hardware/interrupts.h
@@ -0,0 +1,103 @@
+#ifndef INTERRUPTS_H
+#define INTERRUPTS_H
+
+#include <stdint.h>
+
+#include "port.h"
+
+// total number of supported interrupts
+#define NOF_INTERRUPTS 256
+
+// offset for hardware interrupts
+#define IRQ_BASE 0x20
+
+// TCC 0.9.26 bug?, __attribute__( ( packed ) ) on structs not working,
+// also not working on members.. resorting to pragmas
+#if defined( __TINYC__ )
+#pragma pack(1)
+#endif
+
+// packed IDT structure, note TCC needs every member to have a packed
+// attribute, GCC/Clang are happy with the packed attribute at the
+// structure level
+typedef struct interrupt_gate_descriptor_t {
+ uint16_t handler_address_low_bits;
+ uint16_t gdt_code_segment_selector;
+ uint8_t reserved;
+ uint8_t access;
+ uint16_t handler_address_high_bits;
+} __attribute__( ( packed ) ) interrupt_gate_descriptor_t;
+
+#if defined( __TINYC__ )
+#pragma pack()
+#endif
+
+#if defined( __TINYC__ )
+#pragma pack(1)
+#endif
+
+typedef struct {
+ uint16_t size;
+ uint32_t base;
+} __attribute__( ( packed ) ) interrupt_descriptor_table_pointer_t;
+
+#if defined( __TINYC__ )
+#pragma pack()
+#endif
+
+struct interrupt_t;
+struct interrupt_handler_t;
+
+typedef uint32_t (*interrupt_handler_func_t)( struct interrupt_handler_t *handler, uint32_t esp );
+
+typedef struct interrupt_handler_t {
+ uint8_t interrupt_no;
+ struct interrupt_t *interrupt;
+ interrupt_handler_func_t handle;
+ void *driver;
+} interrupt_handler_t;
+
+void interrupt_handler_init_void( interrupt_handler_t *handler );
+void interrupt_handler_init( interrupt_handler_t *handler, uint8_t interrupt_no, struct interrupt_t *interrupt, interrupt_handler_func_t handle, void *driver );
+
+typedef struct interrupt_t {
+ interrupt_descriptor_table_pointer_t idt_pointer;
+ interrupt_gate_descriptor_t descriptor_table[NOF_INTERRUPTS];
+ interrupt_handler_t interrupt_handler[NOF_INTERRUPTS];
+ // PIC master control register: command and status register
+ port8_t PIC_master_control;
+ // PIC master data register: interrupt mask and data register
+ 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 );
+void interrupts_disable( void );
+void interrupts_init( interrupt_t *interrupt );
+void interrupts_register_interrupt_gate( interrupt_t *interrupt,
+ uint8_t interrupt_no, uint16_t gdt_code_segment_selector,
+ void (*helper_handler)( ), uint8_t privilege_level, uint8_t descriptor_type );
+void interrupts_register_interrupt_handler( interrupt_handler_t handler );
+
+void interrupts_load_idt( interrupt_descriptor_table_pointer_t *idt_pointer );
+
+uint32_t interrupts_handle_interrupt( interrupt_t *interrupt, uint8_t interrupt_no, uint32_t esp );
+
+uint32_t interrupts_handle_static_interrupt( uint8_t interrupt_no, uint32_t esp );
+
+uint32_t interrupts_exception_division_by_zero( interrupt_handler_t *handler, uint32_t esp );
+
+uint32_t interrupts_interrupt_PIT( interrupt_handler_t *handler, uint32_t esp );
+
+void interrupts_ignore_request( );
+void interrupts_handle_exception_0x00( );
+void interrupts_handle_irq_0x00( );
+void interrupts_handle_irq_0x01( );
+void interrupts_handle_irq_0x0C( );
+
+// later: tasks and stacks, queues
+
+#endif // INTERRUPTS_H