diff --git a/cpu/x86/drivers/pic.c b/cpu/x86/drivers/pic.c index 2e6428756..12b79e39b 100644 --- a/cpu/x86/drivers/pic.c +++ b/cpu/x86/drivers/pic.c @@ -30,6 +30,8 @@ #include "drivers/pic.h" +#define PIC_ACK 0x20 + void pic_unmask_irq(unsigned int num) { @@ -46,3 +48,13 @@ pic_unmask_irq(unsigned int num) bitmap = inb(port); outb(port, bitmap & ~BIT(num)); } +/*---------------------------------------------------------------------------*/ +void +pic_eoi(unsigned int irq) +{ + if(irq >= 8) { + outb(PIC2_CMD_PORT, PIC_ACK); + } + + outb(PIC1_CMD_PORT, PIC_ACK); +} diff --git a/cpu/x86/drivers/pic.h b/cpu/x86/drivers/pic.h index 81de51e7b..d39942438 100644 --- a/cpu/x86/drivers/pic.h +++ b/cpu/x86/drivers/pic.h @@ -37,6 +37,14 @@ #define PIC1_DATA_PORT 0x21 #define PIC2_CMD_PORT 0xA0 #define PIC2_DATA_PORT 0xA1 +#define PIC1_OFFSET 0x20 +#define PIC2_OFFSET PIC1_OFFSET + 8 + +/* + * Returns the actual interrupt number of a given IRQ, + * no matter which PIC it is part of. + */ +#define PIC_INT(a) (a + PIC1_OFFSET) void pic_unmask_irq(unsigned int num); @@ -52,8 +60,8 @@ pic_init(void) outb(PIC2_CMD_PORT, 0x11); /* ICW2: Remap IRQs by setting an IDT Offset for each PIC. */ - outb(PIC1_DATA_PORT, 0x20); - outb(PIC2_DATA_PORT, 0x28); + outb(PIC1_DATA_PORT, PIC1_OFFSET); + outb(PIC2_DATA_PORT, PIC2_OFFSET); /* ICW3: Setup Slave to Master's IRQ2. */ outb(PIC1_DATA_PORT, 0x04); @@ -69,4 +77,10 @@ pic_init(void) outb(PIC2_DATA_PORT, 0xff); } +/* + * This function sends an end-of-interrupt (EOI) to the correct PIC according + * to the IRQ line number. + */ +void pic_eoi(unsigned int irq); + #endif /* PIC_H */ diff --git a/cpu/x86/drivers/pit.c b/cpu/x86/drivers/pit.c index 9eeb38523..557b27985 100644 --- a/cpu/x86/drivers/pit.c +++ b/cpu/x86/drivers/pit.c @@ -39,6 +39,8 @@ #define PIT_CONTROL_PORT 0x43 #define PIT_COUNTER0_PORT 0x40 #define PIT_CLOCK_FREQUENCY 1193182 +#define PIT_IRQ 0 +#define PIT_INT PIC_INT(PIT_IRQ) static pit_int_callback interrupt_cb; @@ -47,15 +49,13 @@ pit_int_handler(void) { interrupt_cb(); - /* FIXME: Add a pic_send_eoi() API or similar and call it here. */ - outb(0x20, 0x20); /* master PIC */ + pic_eoi(PIT_IRQ); } /*---------------------------------------------------------------------------*/ void pit_init(uint32_t ticks_rate, pit_int_callback cb) { - /* FIXME: Call some PIC API to get the current offset and then add to its default IRQ number (0). */ - SET_INTERRUPT_HANDLER(32, 0, pit_int_handler); + SET_INTERRUPT_HANDLER(PIT_INT, 0, pit_int_handler); interrupt_cb = cb; @@ -76,5 +76,5 @@ pit_init(uint32_t ticks_rate, pit_int_callback cb) outb(PIT_COUNTER0_PORT, divisor & 0xFF); /* Write least significant bytes first. */ outb(PIT_COUNTER0_PORT, (divisor >> 8) & 0xFF); - pic_unmask_irq(0); + pic_unmask_irq(PIT_IRQ); } diff --git a/cpu/x86/drivers/rtc.c b/cpu/x86/drivers/rtc.c index 243c6623f..ad9eec221 100644 --- a/cpu/x86/drivers/rtc.c +++ b/cpu/x86/drivers/rtc.c @@ -35,6 +35,8 @@ #define RTC_INDEX_REGISTER 0x70 #define RTC_TARGET_REGISTER 0x71 +#define RTC_IRQ 8 +#define RTC_INT PIC_INT(RTC_IRQ) static void (*user_callback)(void); @@ -51,8 +53,7 @@ rtc_handler() inb(RTC_TARGET_REGISTER); /* Issue the End of Interrupt to PIC */ - outb(0xA0, 0x20); - outb(0x20, 0x20); + pic_eoi(RTC_IRQ); } /*---------------------------------------------------------------------------*/ /* Initialize the Real Time Clock. @@ -69,10 +70,7 @@ rtc_init(rtc_frequency_t frequency, void (*callback)(void)) user_callback = callback; - /* FIXME: Once we have a proper API to ask PIC what is the IRQ offset, we - * should consider using it here. - */ - SET_INTERRUPT_HANDLER(40, 0, rtc_handler); + SET_INTERRUPT_HANDLER(RTC_INT, 0, rtc_handler); /* Select interrupt period to 7.8125 ms */ outb(RTC_INDEX_REGISTER, 0x0A); @@ -88,5 +86,5 @@ rtc_init(rtc_frequency_t frequency, void (*callback)(void)) outb(RTC_INDEX_REGISTER, 0x0B); outb(RTC_TARGET_REGISTER, reg_b | BIT(6)); - pic_unmask_irq(8); + pic_unmask_irq(RTC_IRQ); }