diff options
Diffstat (limited to 'src/hardware/interrupts.h')
-rw-r--r-- | src/hardware/interrupts.h | 103 |
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 |