PIC helper functions to read the ISR, IRR, and IMR
[akaros.git] / kern / arch / i686 / apic.c
index c220f17..4a930b9 100644 (file)
 
 system_timing_t RO system_timing = {0, 0, 0xffff, 0};
 
-/*
- * Remaps the Programmable Interrupt Controller to use IRQs 32-47
+/* * Remaps the Programmable Interrupt Controller to use IRQs 32-47
  * http://wiki.osdev.org/PIC
- * Not 100% on this stuff, after looking over 
- * http://bochs.sourceforge.net/techspec/PORTS.LST  The cascading and other 
- * stuff might need to be in one command, and after that all we are doing
- * is toggling masks.
- */
+ * Check osdev for a more thorough explanation/implementation.
+ * http://bochs.sourceforge.net/techspec/PORTS.LST  */
 void pic_remap() 
 {
-       // start initialization
+       /* start initialization (ICW1) */
        outb(PIC1_CMD, 0x11);
        outb(PIC2_CMD, 0x11);
-       // set new offsets
+       /* set new offsets (ICW2) */
        outb(PIC1_DATA, PIC1_OFFSET);
        outb(PIC2_DATA, PIC2_OFFSET);
-       // set up cascading
+       /* set up cascading (ICW3) */
        outb(PIC1_DATA, 0x04);
        outb(PIC2_DATA, 0x02);
-       // other stuff (put in 8086/88 mode, or whatever)
+       /* other stuff (put in 8086/88 mode, or whatever) (ICW4) */
        outb(PIC1_DATA, 0x01);
        outb(PIC2_DATA, 0x01);
-       // set masks, defaulting to all masked for now
+       /* Init done, further data R/W access the interrupt mask */
+       /* set masks, defaulting to all masked for now */
        outb(PIC1_DATA, 0xff);
        outb(PIC2_DATA, 0xff);
 }
@@ -63,6 +60,33 @@ void pic_unmask_irq(uint8_t irq)
                outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq));
 }
 
+/* Aka, the IMR.  Simply reading the data port are OCW1s. */
+uint16_t pic_get_mask(void)
+{
+       return (inb(PIC2_DATA) << 8) | inb(PIC1_DATA);
+}
+
+static uint16_t __pic_get_irq_reg(int ocw3)
+{
+       /* OCW3 to PIC CMD to get the register values.  PIC2 is chained, and
+        * represents IRQs 8-15.  PIC1 is IRQs 0-7, with 2 being the chain */
+       outb(PIC1_CMD, ocw3);
+       outb(PIC2_CMD, ocw3);
+       return (inb(PIC2_CMD) << 8) | inb(PIC1_CMD);
+}
+
+/* Returns the combined value of the cascaded PICs irq request register */
+uint16_t pic_get_irr(void)
+{
+       return __pic_get_irq_reg(PIC_READ_IRR);
+}
+
+/* Returns the combined value of the cascaded PICs irq service register */
+uint16_t pic_get_isr(void)
+{
+       return __pic_get_irq_reg(PIC_READ_ISR);
+}
+
 /*
  * Sets the LAPIC timer to go off after a certain number of ticks.  The primary
  * clock freq is actually the bus clock, which we figure out during timer_init
@@ -102,7 +126,7 @@ void set_core_timer(uint32_t usec, bool periodic)
 uint32_t lapic_get_default_id(void)
 {
        uint32_t ebx;
-       cpuid(1, 0, &ebx, 0, 0);
+       cpuid(0x1, 0x0, 0, &ebx, 0, 0);
        // p6 family only uses 4 bits here, and 0xf is reserved for the IOAPIC
        return (ebx & 0xFF000000) >> 24;
 }