Last active
August 27, 2023 04:18
-
-
Save FedorLap2006/0ba8dd66a60f332460246217fbe63f39 to your computer and use it in GitHub Desktop.
x86 customizable PIC handler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "pic.h" // Replace with an actual header | |
#define PIC_PRIMARY_CMD_PORT 0x20 | |
#define PIC_SECONDARY_CMD_PORT 0x20 | |
#define PIC_PRIMARY_DATA_PORT 0x21 | |
#define PIC_SECONDARY_DATA_PORT 0xA1 | |
static void pic_iowait() { __asm__ volatile("outb %%al, $0x80" : : "a"(0)); } | |
struct pic_config current_pic_config; | |
void pic_init(struct pic_config cfg) { | |
uint8_t primary_mask, secondary_mask; | |
/** | |
* Saving old IRQs mask | |
*/ | |
if (cfg.dirty_mask) { | |
primary_mask = inb(PIC_PRIMARY_DATA_PORT) | (~(cfg.mask) & 0xFF); | |
secondary_mask = inb(PIC_SECONDARY_DATA_PORT) | (~(cfg.mask) >> 0x8); | |
} else { | |
primary_mask = ~(cfg.mask & 0xFF); | |
secondary_mask = ~(cfg.mask >> 0x8); | |
} | |
/** | |
* Remaping interrupts table | |
*/ | |
outb(PIC_PRIMARY_CMD_PORT, | |
0x11); /* Initialisation signal + ICW4 mode [primary] */ | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_SECONDARY_CMD_PORT, | |
0x11); /* Initialisation signal + ICW4 mode [secondary] */ | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_PRIMARY_DATA_PORT, | |
cfg.primary_offset); /* Interrupts offset [primary] */ | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_SECONDARY_DATA_PORT, | |
cfg.secondary_offset); /* Interrupts offset [secondary] */ | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_PRIMARY_DATA_PORT, | |
cfg.sconn_irq_line); /* IRQ lines where secondary controller is | |
connected [primary] */ | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_SECONDARY_DATA_PORT, | |
cfg.sec_irq_line_num); /* IRQ line number where secondary | |
controller is connected [secondary] */ | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_PRIMARY_DATA_PORT, | |
(uint8_t)(0 | ((cfg.mp_mode & 0x1) << 0) | ((cfg.auto_eoi & 0x1) << 1) | | |
((cfg.bufmode & 0x1) << 2) | ((cfg.ps_bufmode & 0x1) << 3) | | |
((cfg.sfn_mode & 0x1) << 4))); | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_SECONDARY_DATA_PORT, | |
(uint8_t)(0 | ((cfg.mp_mode & 0x1) << 0) | ((cfg.auto_eoi & 0x1) << 1) | | |
((cfg.bufmode & 0x1) << 2) | ((cfg.ps_bufmode & 0x1) << 3) | | |
((cfg.sfn_mode & 0x1) << 4))); | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_PRIMARY_DATA_PORT, primary_mask); | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
outb(PIC_SECONDARY_DATA_PORT, secondary_mask); | |
if (cfg.iowait_mode) | |
pic_iowait(); | |
current_pic_config = cfg; | |
} | |
void pic_eoi(uint32_t int_num) { | |
if (current_pic_config.auto_eoi) | |
return; | |
if (int_num >= 40) { | |
outb(0xA0, 0x20); | |
} | |
outb(0x20, 0x20); | |
} | |
struct pic_config default_pic_config = { | |
.dirty_mask = false, | |
.iowait_mode = true, | |
.sfn_mode = false, | |
.bufmode = false, | |
.ps_bufmode = false, | |
.auto_eoi = false, | |
.mp_mode = true, | |
.primary_offset = 0x20, | |
.secondary_offset = 0x28, | |
.sec_irq_line_num = 0x2, | |
.sconn_irq_line = 0x4, | |
.mask = (uint16_t)IRQCALL, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <types.h> // Replace with an actual header | |
typedef struct pic_config { | |
/** | |
* Dirty old mask flag | |
* | |
* If set new mask will contain result of an OR operation between old and new masks. | |
* Otherwise, old mask will be cleared and will be replaced by new one. | |
*/ | |
bool dirty_mask; | |
/** | |
* IOwait mode flag | |
* | |
* Whether to use iowait mode after every PIC command execution | |
* NOTE: It must be set to true on an old processor. | |
*/ | |
bool iowait_mode; | |
/** | |
* Special Fully Nested Mode (SFNM) flag | |
* | |
* NOTE: It is recommended to leave it unset. | |
*/ | |
bool sfn_mode; | |
/** | |
* Buffered mode | |
* | |
* NOTE: It must be set to false for the Intel ICH4 | |
*/ | |
bool bufmode; | |
/** | |
* Primary-secondary (master-slave) buffered mode | |
* | |
* NOTE: Should always be set to false on the Intel architecture | |
*/ | |
bool ps_bufmode; | |
/** | |
* Auto EOI | |
* | |
* Whether to automatically send EOI after the interrupt finishes execution. | |
*/ | |
bool auto_eoi; | |
/** | |
* Microprocessor mode | |
* NOTE: Must be be set to true on the Intel architecture. | |
*/ | |
bool mp_mode; | |
/** | |
* Offset of the interrupts in the IDT which would controlled by the primary controller | |
* | |
* NOTE: Recommended set it to 0x20 on the Intel architecture. | |
*/ | |
uint8_t primary_offset; | |
/** | |
* Offset of the interrupts in the IDT which would controlled by the secondary controller | |
* | |
* NOTE: Recommended set it to 0x28 | |
*/ | |
uint8_t secondary_offset; | |
/** | |
* IRQ line number on which the secondary controller is connected | |
* | |
* NOTE: Must be set to 0x2 on the PC. | |
*/ | |
uint8_t sec_irq_line_num; | |
/** | |
* IRQ lines on which the secondary controller(s) is connected | |
* | |
* NOTE: Must be set to 0x4 on the PC. | |
*/ | |
uint8_t sconn_irq_line; | |
/** | |
* Bitmask of enabled IRQ lines | |
*/ | |
uint16_t mask; | |
} pic_config_t; | |
#define IRQC0 (1 << 0) | |
#define IRQC1 (1 << 1) | |
#define IRQC2 (1 << 2) | |
#define IRQC3 (1 << 3) | |
#define IRQC4 (1 << 4) | |
#define IRQC5 (1 << 5) | |
#define IRQC6 (1 << 6) | |
#define IRQC7 (1 << 7) | |
#define IRQC8 (1 << 8) | |
#define IRQC9 (1 << 9) | |
#define IRQC10 (1 << 10) | |
#define IRQC11 (1 << 11) | |
#define IRQC12 (1 << 12) | |
#define IRQC13 (1 << 13) | |
#define IRQC14 (1 << 14) | |
#define IRQC15 (1 << 15) | |
#define IRQC16 (1 << 16) | |
#define IRQCALL 0xFFFF // Enable all | |
#define IRQCDALL 0x0000 // Disable all | |
void pic_init(struct pic_config cfg); | |
void pic_eoi(uint32_t int_num); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment