Enable a default hw irq handler.

Also, only route hw irqs to their handlers when they are enabled.
    (This ensures that if a subsystem is disabled that the default
    hwirq handler will be used.)
Add helper macros to declare the extern asm handlers.
Always enable the RTC hwirq at startup (as opposed to when it is first
    used).
Fix bug in default handler - wrong bit was used for checking the
    cascaded irq.
diff --git a/src/ata.c b/src/ata.c
index d0fef06..a15dc0f 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -10,7 +10,7 @@
 #include "ioport.h" // inb
 #include "util.h" // dprintf
 #include "cmos.h" // inb_cmos
-#include "pic.h" // unmask_pic2
+#include "pic.h" // enable_hwirq
 #include "biosvar.h" // GET_EBDA
 #include "pci.h" // pci_find_class
 #include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
@@ -972,6 +972,5 @@
 
     SET_BDA(disk_control_byte, 0xc0);
 
-    // Enable IRQ14 (handle_76)
-    unmask_pic2(PIC2_IRQ14);
+    enable_hwirq(14, entry_76);
 }
diff --git a/src/clock.c b/src/clock.c
index a490a9b..e786fb4 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -9,7 +9,7 @@
 #include "util.h" // debug_enter
 #include "disk.h" // floppy_tick
 #include "cmos.h" // inb_cmos
-#include "pic.h" // unmask_pic1
+#include "pic.h" // eoi_pic1
 #include "bregs.h" // struct bregs
 
 // RTC register flags
@@ -55,8 +55,8 @@
     SET_BDA(timer_counter, ticks);
     SET_BDA(timer_rollover, 0);
 
-    // Enable IRQ0 (handle_08)
-    unmask_pic1(PIC1_IRQ0);
+    enable_hwirq(0, entry_08);
+    enable_hwirq(8, entry_70);
 }
 
 static void
@@ -239,7 +239,6 @@
     outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM);
     outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM);
     outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM);
-    unmask_pic2(PIC2_IRQ8); // enable IRQ 8
     // enable Status Reg B alarm bit, clear halt clock bit
     outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B);
     set_success(regs);
@@ -346,8 +345,6 @@
     SET_BDA(ptr_user_wait_complete_flag, (seg << 16) | offset);
     SET_BDA(user_wait_timeout, usecs);
 
-    // Unmask IRQ8 so INT70 will get through.
-    unmask_pic2(PIC2_IRQ8);
     // Turn on the Periodic Interrupt timer
     u8 bRegister = inb_cmos(CMOS_STATUS_B);
     outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B);
@@ -396,8 +393,7 @@
 
 #define RET_ECLOCKINUSE  0x83
 
-// Wait for CX:DX microseconds. currently using the
-// refresh request port 0x61 bit4, toggling every 15usec
+// Wait for CX:DX microseconds
 void
 handle_1586(struct bregs *regs)
 {
diff --git a/src/floppy.c b/src/floppy.c
index 4f7d4af..c880478 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -11,7 +11,7 @@
 #include "biosvar.h" // SET_BDA
 #include "util.h" // irq_disable
 #include "cmos.h" // inb_cmos
-#include "pic.h" // unmask_pic1
+#include "pic.h" // eoi_pic1
 #include "bregs.h" // struct bregs
 
 #define BX_FLOPPY_ON_CNT 37   /* 2 seconds */
@@ -74,8 +74,7 @@
 
     outb(0x02, PORT_DMA1_MASK_REG);
 
-    // Enable IRQ6 (handle_0e)
-    unmask_pic1(PIC1_IRQ6);
+    enable_hwirq(6, entry_0e);
 }
 
 static inline void
diff --git a/src/kbd.c b/src/kbd.c
index 2d36c31..cb60306 100644
--- a/src/kbd.c
+++ b/src/kbd.c
@@ -97,8 +97,7 @@
 
     keyboard_init();
 
-    // Enable IRQ1 (handle_09)
-    unmask_pic1(PIC1_IRQ1);
+    enable_hwirq(1, entry_09);
 }
 
 static u8
diff --git a/src/mouse.c b/src/mouse.c
index 1435c92..09631bd 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -7,7 +7,7 @@
 
 #include "biosvar.h" // GET_EBDA
 #include "util.h" // debug_isr
-#include "pic.h" // unmask_pic2
+#include "pic.h" // eoi_pic2
 #include "bregs.h" // struct bregs
 #include "ps2port.h" // aux_command
 
@@ -19,8 +19,7 @@
     dprintf(3, "init mouse\n");
     // pointing device installed
     SETBITS_BDA(equipment_list_flags, 0x04);
-    // Enable IRQ12 (handle_74)
-    unmask_pic2(PIC2_IRQ12);
+    enable_hwirq(12, entry_74);
 }
 
 #define RET_SUCCESS      0x00
diff --git a/src/pic.c b/src/pic.c
index f895798..e350d28 100644
--- a/src/pic.c
+++ b/src/pic.c
@@ -49,7 +49,7 @@
         mask_pic2(isr2);
         eoi_pic2();
     } else {
-        if (! (isr1 & 0x2)) // don't ever mask the cascaded irq
+        if (! (isr1 & PIC1_IRQ2)) // don't ever mask the cascaded irq
             mask_pic1(isr1);
         eoi_pic1();
     }
diff --git a/src/pic.h b/src/pic.h
index f020f55..d4228e1 100644
--- a/src/pic.h
+++ b/src/pic.h
@@ -76,6 +76,28 @@
     return inb(PORT_PIC2_CMD);
 }
 
+// post.c
+void __set_irq(int vector, void *loc);
+
+static inline void
+__enable_hwirq(int hwirq, void (*func)(void))
+{
+    int vector;
+    if (hwirq < 8) {
+        unmask_pic1(1 << hwirq);
+        vector = 0x08 + hwirq;
+    } else {
+        unmask_pic2(1 << (hwirq - 8));
+        vector = 0x70 + hwirq - 8;
+    }
+    __set_irq(vector, func);
+}
+
+#define enable_hwirq(irq, func) do {            \
+        extern void func (void);                \
+        __enable_hwirq(irq, func);              \
+    } while (0)
+
 void pic_setup();
 
 #endif // pic.h
diff --git a/src/post.c b/src/post.c
index dc909b2..6f407d9 100644
--- a/src/post.c
+++ b/src/post.c
@@ -21,36 +21,17 @@
 #define bda ((struct bios_data_area_s *)MAKE_FARPTR(SEG_BDA, 0))
 #define ebda ((struct extended_bios_data_area_s *)MAKE_FARPTR(SEG_EBDA, 0))
 
-static void
-set_irq(int vector, void *loc)
+void
+__set_irq(int vector, void *loc)
 {
     SET_BDA(ivecs[vector].seg, SEG_BIOS);
     SET_BDA(ivecs[vector].offset, (u32)loc - BUILD_BIOS_ADDR);
 }
 
-// Symbols defined in romlayout.S
-extern void dummy_iret_handler();
-extern void entry_08();
-extern void entry_09();
-extern void entry_hwirq();
-extern void entry_0e();
-extern void entry_10();
-extern void entry_11();
-extern void entry_12();
-extern void entry_13();
-extern void entry_14();
-extern void entry_15();
-extern void entry_16();
-extern void entry_17();
-extern void entry_18();
-extern void entry_19();
-extern void entry_1a();
-extern void entry_1c();
-extern void entry_40();
-extern void entry_70();
-extern void entry_74();
-extern void entry_75();
-extern void entry_76();
+#define set_irq(vector, func) do {              \
+        extern void func (void);                \
+        __set_irq(vector, func);                \
+    } while (0)
 
 static void
 init_bda()
@@ -60,46 +41,38 @@
 
     SET_BDA(mem_size_kb, BASE_MEM_IN_K);
 
+    // Initialize all vectors to a dummy handler.
     int i;
     for (i=0; i<256; i++)
-        set_irq(i, &dummy_iret_handler);
+        set_irq(i, dummy_iret_handler);
 
-    set_irq(0x08, &entry_08);
-    set_irq(0x09, &entry_09);
-    //set_irq(0x0a, &entry_hwirq);
-    //set_irq(0x0b, &entry_hwirq);
-    //set_irq(0x0c, &entry_hwirq);
-    //set_irq(0x0d, &entry_hwirq);
-    set_irq(0x0e, &entry_0e);
-    //set_irq(0x0f, &entry_hwirq);
-    set_irq(0x10, &entry_10);
-    set_irq(0x11, &entry_11);
-    set_irq(0x12, &entry_12);
-    set_irq(0x13, &entry_13);
-    set_irq(0x14, &entry_14);
-    set_irq(0x15, &entry_15);
-    set_irq(0x16, &entry_16);
-    set_irq(0x17, &entry_17);
-    set_irq(0x18, &entry_18);
-    set_irq(0x19, &entry_19);
-    set_irq(0x1a, &entry_1a);
-    set_irq(0x1c, &entry_1c);
-    set_irq(0x40, &entry_40);
-    set_irq(0x70, &entry_70);
-    //set_irq(0x71, &entry_hwirq);
-    //set_irq(0x72, &entry_hwirq);
-    //set_irq(0x73, &entry_hwirq);
-    set_irq(0x74, &entry_74);
-    set_irq(0x75, &entry_75);
-    set_irq(0x76, &entry_76);
-    //set_irq(0x77, &entry_hwirq);
+    // Initialize all hw vectors to a default hw handler.
+    for (i=0x08; i<=0x0f; i++)
+        set_irq(i, entry_hwirq);
+    for (i=0x70; i<=0x77; i++)
+        set_irq(i, entry_hwirq);
+
+    // Initialize software handlers.
+    set_irq(0x10, entry_10);
+    set_irq(0x11, entry_11);
+    set_irq(0x12, entry_12);
+    set_irq(0x13, entry_13);
+    set_irq(0x14, entry_14);
+    set_irq(0x15, entry_15);
+    set_irq(0x16, entry_16);
+    set_irq(0x17, entry_17);
+    set_irq(0x18, entry_18);
+    set_irq(0x19, entry_19);
+    set_irq(0x1a, entry_1a);
+    set_irq(0x1c, entry_1c);
+    set_irq(0x40, entry_40);
 
     // set vector 0x79 to zero
     // this is used by 'gardian angel' protection system
     SET_BDA(ivecs[0x79].seg, 0);
     SET_BDA(ivecs[0x79].offset, 0);
 
-    set_irq(0x1E, &diskette_param_table2);
+    __set_irq(0x1E, &diskette_param_table2);
 }
 
 static void
diff --git a/src/romlayout.S b/src/romlayout.S
index a6bad45..12052d8 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -481,6 +481,7 @@
         ORG 0xe82e
         IRQ_ENTRY_ARG 16
 
+        .global entry_hwirq
 entry_hwirq:
         ENTRY handle_hwirq
 
diff --git a/src/system.c b/src/system.c
index 1c96b98..fdbdffc 100644
--- a/src/system.c
+++ b/src/system.c
@@ -383,8 +383,7 @@
     dprintf(3, "math cp init\n");
     // 80x87 coprocessor installed
     SETBITS_BDA(equipment_list_flags, 0x02);
-    // Enable IRQ13 (handle_75)
-    unmask_pic2(PIC2_IRQ13);
+    enable_hwirq(13, entry_75);
 }
 
 // INT 75 - IRQ13 - MATH COPROCESSOR EXCEPTION