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.
This commit is contained in:
parent
826ff7cb29
commit
afd9b5b0b7
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue