blob: 9a3ea0b47cb4722591c769c14a0da4778b2f7a23 [file] [log] [blame]
Kevin O'Connorc541e1b2008-06-21 12:24:14 -04001// Helpers for working with i8259 interrupt controller.
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4// Copyright (C) 2002 MandrakeSoft S.A.
5//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connorc541e1b2008-06-21 12:24:14 -04007
Kevin O'Connoraa7c2342013-07-14 15:07:21 -04008#include "pic.h" // pic_*
Kevin O'Connor9521e262008-07-04 13:04:29 -04009#include "util.h" // dprintf
10#include "config.h" // CONFIG_*
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040011#include "biosvar.h" // SET_IVT
12
13u16
14pic_irqmask_read(void)
15{
16 return inb(PORT_PIC1_DATA) | (inb(PORT_PIC2_DATA) << 8);
17}
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040018
19void
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040020pic_irqmask_write(u16 mask)
21{
22 outb(mask, PORT_PIC1_DATA);
23 outb(mask >> 8, PORT_PIC2_DATA);
24}
25
26void
27pic_irqmask_mask(u16 off, u16 on)
28{
29 u8 pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
30 outb((inb(PORT_PIC1_DATA) & ~pic1off) | pic1on, PORT_PIC1_DATA);
31 outb((inb(PORT_PIC2_DATA) & ~pic2off) | pic2on, PORT_PIC2_DATA);
32}
33
34void
35pic_reset(u8 irq0, u8 irq8)
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040036{
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040037 // Send ICW1 (select OCW1 + will send ICW4)
38 outb(0x11, PORT_PIC1_CMD);
39 outb(0x11, PORT_PIC2_CMD);
Kevin O'Connor65e63422008-07-19 14:12:32 -040040 // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15)
Kevin O'Connor643062f2010-01-04 20:48:20 -050041 outb(irq0, PORT_PIC1_DATA);
42 outb(irq8, PORT_PIC2_DATA);
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040043 // Send ICW3 (cascaded pic ids)
44 outb(0x04, PORT_PIC1_DATA);
45 outb(0x02, PORT_PIC2_DATA);
46 // Send ICW4 (enable 8086 mode)
47 outb(0x01, PORT_PIC1_DATA);
48 outb(0x01, PORT_PIC2_DATA);
49 // Mask all irqs (except cascaded PIC2 irq)
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040050 pic_irqmask_write(PIC_IRQMASK_DEFAULT);
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040051}
52
Kevin O'Connor643062f2010-01-04 20:48:20 -050053void
54pic_setup(void)
55{
56 dprintf(3, "init pic\n");
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040057 pic_reset(BIOS_HWIRQ0_VECTOR, BIOS_HWIRQ8_VECTOR);
58}
59
60void
61enable_hwirq(int hwirq, struct segoff_s func)
62{
63 pic_irqmask_mask(1 << hwirq, 0);
64 int vector;
65 if (hwirq < 8)
66 vector = BIOS_HWIRQ0_VECTOR + hwirq;
67 else
68 vector = BIOS_HWIRQ8_VECTOR + hwirq - 8;
69 SET_IVT(vector, func);
70}
71
72static u8
73pic_isr1_read(void)
74{
75 // 0x0b == select OCW1 + read ISR
76 outb(0x0b, PORT_PIC1_CMD);
77 return inb(PORT_PIC1_CMD);
78}
79
80static u8
81pic_isr2_read(void)
82{
83 // 0x0b == select OCW1 + read ISR
84 outb(0x0b, PORT_PIC2_CMD);
85 return inb(PORT_PIC2_CMD);
Kevin O'Connor643062f2010-01-04 20:48:20 -050086}
87
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040088// Handler for otherwise unused hardware irqs.
89void VISIBLE16
Kevin O'Connorffdc9ee2008-12-20 13:10:00 -050090handle_hwpic1(struct bregs *regs)
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040091{
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040092 dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", pic_isr1_read());
93 pic_eoi1();
Kevin O'Connorffdc9ee2008-12-20 13:10:00 -050094}
Kevin O'Connorc541e1b2008-06-21 12:24:14 -040095
Kevin O'Connorffdc9ee2008-12-20 13:10:00 -050096void VISIBLE16
97handle_hwpic2(struct bregs *regs)
98{
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040099 dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", pic_isr2_read());
100 pic_eoi2();
David Woodhousefbdbb4b2013-02-05 16:37:27 +0000101}