From afd9b5b0b7b2dcbf964ff7955890777a60919949 Mon Sep 17 00:00:00 2001 From: Jesus Sanchez-Palencia Date: Thu, 2 Jul 2015 18:24:20 -0300 Subject: [PATCH] x86: Add APIs to 8259 PIC driver This commit implements pic_eoi(int irq) and a helper macro PIC_INT(irq). This first checks which PICs should be 'acked' given an IRQ number, while the macro returns the actual system interrupt number for the IRQ according to the offset used on the PIC initialization. --- cpu/x86/drivers/pic.c | 12 ++++++++++++ cpu/x86/drivers/pic.h | 18 ++++++++++++++++-- cpu/x86/drivers/pit.c | 10 +++++----- cpu/x86/drivers/rtc.c | 12 +++++------- 4 files changed, 38 insertions(+), 14 deletions(-) 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); }