+#include "intr.h"
+
+/* PIC command and data ports */
+#define PIC1_CMD 0x20
+#define PIC1_DATA 0x21
+#define PIC2_CMD 0xa0
+#define PIC2_DATA 0xa1
+
+/* PIC initialization command word 1 bits */
+#define ICW1_ICW4_NEEDED (1 << 0)
+#define ICW1_SINGLE (1 << 1)
+#define ICW1_INTERVAL4 (1 << 2)
+#define ICW1_LEVEL (1 << 3)
+#define ICW1_INIT (1 << 4)
+/* PIC initialization command word 4 bits */
+#define ICW4_8086 (1 << 0)
+#define ICW4_AUTO_EOI (1 << 1)
+#define ICW4_BUF_SLAVE (1 << 3) /* 1000 */
+#define ICW4_BUF_MASTER (3 << 2) /* 1100 */
+#define ICW4_SPECIAL (1 << 4)
+/* PIC operation command word 2 bits */
+#define OCW2_EOI (1 << 5)
+
+
+#define MAX_INTR 32
+static intr_func_t intrfunc[MAX_INTR];
+
+static void (*intr_unhandled)(struct intr_frame *frm);
+
+void intr_entry_div();
+void intr_entry_trap();
+void intr_entry_nmi();
+void intr_entry_break();
+void intr_entry_ovf();
+void intr_entry_bound();
+void intr_entry_ill();
+void intr_entry_irq0();
+void intr_entry_irq1();
+void intr_entry_irq2();
+void intr_entry_irq3();
+void intr_entry_irq4();
+void intr_entry_irq5();
+void intr_entry_irq6();
+void intr_entry_irq7();
+
+extern int _kern_start_seg;
+#define KERN_CS ((uint16_t)(&_kern_start_seg))
+
+
+void init_intr(void)
+{
+ int i;
+
+ for(i=0; i<MAX_INTR; i++) {
+ intrfunc[i] = 0;
+ }
+
+ set_intr_vect(0, KERN_CS, (uint16_t)intr_entry_div);
+}
+
+void dispatch_intr(struct intr_frame frm)
+{
+ intrfunc[frm.inum](&frm);
+}
+
+void set_intr_vect(int n, uint16_t seg, uint16_t offs)
+{
+ uint16_t *ivt = 0;
+
+ ivt[n * 4] = offs;
+ ivt[n * 4 + 1] = seg;
+}
+
+void set_intr(int n, intr_func_t func)
+{
+ intrfunc[n] = func;
+}
+
+void mask_irq(int n)
+{
+ int port;
+ unsigned char mask;
+
+ if(n < 8) {
+ port = PIC1_DATA;
+ } else {
+ port = PIC2_DATA;
+ n -= 8;
+ }
+
+ mask = inp(port) | (1 << n);
+ outp(port, mask);
+}
+
+void unmask_irq(int n)
+{
+ int port;
+ unsigned char mask;
+
+ if(n < 8) {
+ port = PIC1_DATA;
+ } else {
+ port = PIC2_DATA;
+ n -= 8;
+ }
+
+ mask = inp(port) & ~(1 << n);
+ outp(port, mask);
+}