x86: moves the PIC into its own file
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 12 Mar 2014 03:01:34 +0000 (20:01 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 29 Mar 2014 01:16:10 +0000 (18:16 -0700)
kern/arch/x86/Kbuild
kern/arch/x86/apic.c
kern/arch/x86/apic.h
kern/arch/x86/pic.c [new file with mode: 0644]
kern/arch/x86/pic.h [new file with mode: 0644]
kern/arch/x86/trap.h
kern/src/testing.c

index 8ed739b..920096c 100644 (file)
@@ -14,6 +14,7 @@ obj-y                                         += mpacpi.o
 obj-y                                          += mp.o
 obj-y                                          += page_alloc.o
 obj-y                                          += pci.o
+obj-y                                          += pic.o
 obj-y                                          += perfmon.o
 obj-y                                          += pmap.o pmap$(BITS).o
 obj-y                                          += process$(BITS).o
index 51c9374..7df5d35 100644 (file)
 #include <stdio.h>
 #include <bitmask.h>
 #include <arch/coreid.h>
+#include <arch/pic.h>
 
 system_timing_t RO system_timing = {0, 0, 0xffff, 0};
 bool core_id_ready = FALSE;
-spinlock_t piclock = SPINLOCK_INITIALIZER_IRQSAVE;
-
-/* * Remaps the Programmable Interrupt Controller to use IRQs 32-47
- * http://wiki.osdev.org/PIC
- * Check osdev for a more thorough explanation/implementation.
- * http://bochs.sourceforge.net/techspec/PORTS.LST  */
-void pic_remap(void)
-{
-       spin_lock_irqsave(&piclock);
-       /* start initialization (ICW1) */
-       outb(PIC1_CMD, 0x11);
-       outb(PIC2_CMD, 0x11);
-       /* set new offsets (ICW2) */
-       outb(PIC1_DATA, PIC1_OFFSET);
-       outb(PIC2_DATA, PIC2_OFFSET);
-       /* set up cascading (ICW3) */
-       outb(PIC1_DATA, 0x04);
-       outb(PIC2_DATA, 0x02);
-       /* other stuff (put in 8086/88 mode, or whatever) (ICW4) */
-       outb(PIC1_DATA, 0x01);
-       outb(PIC2_DATA, 0x01);
-       /* 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);
-       spin_unlock_irqsave(&piclock);
-}
-
-void pic_mask_irq(int trap_nr)
-{
-       int irq = trap_nr - PIC1_OFFSET;
-       spin_lock_irqsave(&piclock);
-       if (irq > 7)
-               outb(PIC2_DATA, inb(PIC2_DATA) | (1 << (irq - 8)));
-       else
-               outb(PIC1_DATA, inb(PIC1_DATA) | (1 << irq));
-       spin_unlock_irqsave(&piclock);
-}
-
-void pic_unmask_irq(int trap_nr)
-{
-       int irq = trap_nr - PIC1_OFFSET;
-       spin_lock_irqsave(&piclock);
-       if (irq > 7) {
-               outb(PIC2_DATA, inb(PIC2_DATA) & ~(1 << (irq - 8)));
-               outb(PIC1_DATA, inb(PIC1_DATA) & 0xfb); // make sure irq2 is unmasked
-       } else
-               outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq));
-       spin_unlock_irqsave(&piclock);
-}
-
-void pic_mask_all(void)
-{
-       for (int i = 0 + PIC1_OFFSET; i < 16 + PIC1_OFFSET; i++)
-               pic_mask_irq(i);
-}
-
-/* Aka, the IMR.  Simply reading the data port are OCW1s. */
-uint16_t pic_get_mask(void)
-{
-       uint16_t ret;
-       spin_lock_irqsave(&piclock);
-       ret = (inb(PIC2_DATA) << 8) | inb(PIC1_DATA);
-       spin_unlock_irqsave(&piclock);
-       return ret;
-}
-
-static uint16_t __pic_get_irq_reg(int ocw3)
-{
-       uint16_t ret;
-       spin_lock_irqsave(&piclock);
-       /* 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);
-       ret = (inb(PIC2_CMD) << 8) | inb(PIC1_CMD);
-       spin_unlock_irqsave(&piclock);
-       return ret;
-}
-
-/* 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);
-}
-
-/* Takes a raw vector/trap number (32-47), not a device IRQ (0-15) */
-bool pic_check_spurious(int trap_nr)
-{
-       /* the PIC may send spurious irqs via one of the chips irq 7.  if the isr
-        * doesn't show that irq, then it was spurious, and we don't send an eoi.
-        * Check out http://wiki.osdev.org/8259_PIC#Spurious_IRQs */
-       if ((trap_nr == PIC1_SPURIOUS) && !(pic_get_isr() & (1 << 7))) {
-               printd("Spurious PIC1 irq!\n"); /* want to know if this happens */
-               return TRUE;
-       }
-       if ((trap_nr == PIC2_SPURIOUS) && !(pic_get_isr() & (1 << 15))) {
-               printd("Spurious PIC2 irq!\n"); /* want to know if this happens */
-               /* for the cascaded PIC, we *do* need to send an EOI to the master's
-                * cascade irq (2). */
-               pic_send_eoi(2 + PIC1_OFFSET);
-               return TRUE;
-       }
-       return FALSE;
-}
-
-void pic_send_eoi(int trap_nr)
-{
-       int irq = trap_nr - PIC1_OFFSET;
-       spin_lock_irqsave(&piclock);
-       // all irqs beyond the first seven need to be chained to the slave
-       if (irq > 7)
-               outb(PIC2_CMD, PIC_EOI);
-       outb(PIC1_CMD, PIC_EOI);
-       spin_unlock_irqsave(&piclock);
-}
 
 bool lapic_check_spurious(int trap_nr)
 {
index b0fbaa2..363d2af 100644 (file)
 #include <arch/x86.h>
 #include <atomic.h>
 
-/* PIC (8259A)
- * When looking at the specs, A0 is our CMD line, and A1 is the DATA line.  This
- * means that blindly writing to PIC1_DATA is an OCW1 (interrupt masks).  When
- * writing to CMD (A0), the chip can determine betweeb OCW2 and OCW3 by the
- * setting of a few specific bits (OCW2 has bit 3 unset, OCW3 has it set). */
-#define PIC1_CMD                                       0x20
-#define PIC1_DATA                                      0x21
-#define PIC2_CMD                                       0xA0
-#define PIC2_DATA                                      0xA1
-// These are also hardcoded into the IRQ_HANDLERs of kern/trapentry.S
-#define PIC1_OFFSET                                    0x20
-#define PIC2_OFFSET                                    0x28
-#define PIC1_SPURIOUS                          (7 + PIC1_OFFSET)
-#define PIC2_SPURIOUS                          (7 + PIC2_OFFSET)
-#define PIC_EOI                                                0x20    /* OCW2 EOI */
-/* These set the next CMD read to return specific values.  Note that the chip
- * remembers what setting we had before (IRR or ISR), if you do other reads of
- * CMD. (not tested, written in the spec sheet) */
-#define PIC_READ_IRR                           0x0a    /* OCW3 irq ready next CMD read */
-#define PIC_READ_ISR                           0x0b    /* OCW3 irq service next CMD read */
-
 // Local APIC
 /* PBASE is the physical address.  It is mapped in at the VADDR LAPIC_BASE.
  * 64 bit note: it looks like this is mapped to the same place in 64 bit address
@@ -137,15 +116,6 @@ extern system_timing_t system_timing;
  * other than core 0 when it is called before smp_boot completes. */
 extern bool core_id_ready;
 
-void pic_remap(void);
-void pic_mask_irq(int trap_nr);
-void pic_unmask_irq(int trap_nr);
-void pic_mask_all(void);
-uint16_t pic_get_mask(void);
-uint16_t pic_get_irr(void);
-uint16_t pic_get_isr(void);
-bool pic_check_spurious(int trap_nr);
-void pic_send_eoi(int trap_nr);
 bool lapic_check_spurious(int trap_nr);
 bool lapic_get_isr_bit(uint8_t vector);
 bool lapic_get_irr_bit(uint8_t vector);
diff --git a/kern/arch/x86/pic.c b/kern/arch/x86/pic.c
new file mode 100644 (file)
index 0000000..569f77e
--- /dev/null
@@ -0,0 +1,134 @@
+/* Copyright (c) 2009, 2014 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * PIC: 8259 interrupt controller */
+
+#include <arch/pic.h>
+#include <arch/x86.h>
+#include <atomic.h>
+#include <assert.h>
+#include <stdio.h>
+
+spinlock_t piclock = SPINLOCK_INITIALIZER_IRQSAVE;
+
+/* * Remaps the Programmable Interrupt Controller to use IRQs 32-47
+ * http://wiki.osdev.org/PIC
+ * Check osdev for a more thorough explanation/implementation.
+ * http://bochs.sourceforge.net/techspec/PORTS.LST  */
+void pic_remap(void)
+{
+       spin_lock_irqsave(&piclock);
+       /* start initialization (ICW1) */
+       outb(PIC1_CMD, 0x11);
+       outb(PIC2_CMD, 0x11);
+       /* set new offsets (ICW2) */
+       outb(PIC1_DATA, PIC1_OFFSET);
+       outb(PIC2_DATA, PIC2_OFFSET);
+       /* set up cascading (ICW3) */
+       outb(PIC1_DATA, 0x04);
+       outb(PIC2_DATA, 0x02);
+       /* other stuff (put in 8086/88 mode, or whatever) (ICW4) */
+       outb(PIC1_DATA, 0x01);
+       outb(PIC2_DATA, 0x01);
+       /* 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);
+       spin_unlock_irqsave(&piclock);
+}
+
+void pic_mask_irq(int trap_nr)
+{
+       int irq = trap_nr - PIC1_OFFSET;
+       spin_lock_irqsave(&piclock);
+       if (irq > 7)
+               outb(PIC2_DATA, inb(PIC2_DATA) | (1 << (irq - 8)));
+       else
+               outb(PIC1_DATA, inb(PIC1_DATA) | (1 << irq));
+       spin_unlock_irqsave(&piclock);
+}
+
+void pic_unmask_irq(int trap_nr)
+{
+       int irq = trap_nr - PIC1_OFFSET;
+       spin_lock_irqsave(&piclock);
+       if (irq > 7) {
+               outb(PIC2_DATA, inb(PIC2_DATA) & ~(1 << (irq - 8)));
+               outb(PIC1_DATA, inb(PIC1_DATA) & 0xfb); // make sure irq2 is unmasked
+       } else
+               outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq));
+       spin_unlock_irqsave(&piclock);
+}
+
+void pic_mask_all(void)
+{
+       for (int i = 0 + PIC1_OFFSET; i < 16 + PIC1_OFFSET; i++)
+               pic_mask_irq(i);
+}
+
+/* Aka, the IMR.  Simply reading the data port are OCW1s. */
+uint16_t pic_get_mask(void)
+{
+       uint16_t ret;
+       spin_lock_irqsave(&piclock);
+       ret = (inb(PIC2_DATA) << 8) | inb(PIC1_DATA);
+       spin_unlock_irqsave(&piclock);
+       return ret;
+}
+
+static uint16_t __pic_get_irq_reg(int ocw3)
+{
+       uint16_t ret;
+       spin_lock_irqsave(&piclock);
+       /* 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);
+       ret = (inb(PIC2_CMD) << 8) | inb(PIC1_CMD);
+       spin_unlock_irqsave(&piclock);
+       return ret;
+}
+
+/* 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);
+}
+
+/* Takes a raw vector/trap number (32-47), not a device IRQ (0-15) */
+bool pic_check_spurious(int trap_nr)
+{
+       /* the PIC may send spurious irqs via one of the chips irq 7.  if the isr
+        * doesn't show that irq, then it was spurious, and we don't send an eoi.
+        * Check out http://wiki.osdev.org/8259_PIC#Spurious_IRQs */
+       if ((trap_nr == PIC1_SPURIOUS) && !(pic_get_isr() & (1 << 7))) {
+               printd("Spurious PIC1 irq!\n"); /* want to know if this happens */
+               return TRUE;
+       }
+       if ((trap_nr == PIC2_SPURIOUS) && !(pic_get_isr() & (1 << 15))) {
+               printd("Spurious PIC2 irq!\n"); /* want to know if this happens */
+               /* for the cascaded PIC, we *do* need to send an EOI to the master's
+                * cascade irq (2). */
+               pic_send_eoi(2 + PIC1_OFFSET);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+void pic_send_eoi(int trap_nr)
+{
+       int irq = trap_nr - PIC1_OFFSET;
+       spin_lock_irqsave(&piclock);
+       // all irqs beyond the first seven need to be chained to the slave
+       if (irq > 7)
+               outb(PIC2_CMD, PIC_EOI);
+       outb(PIC1_CMD, PIC_EOI);
+       spin_unlock_irqsave(&piclock);
+}
diff --git a/kern/arch/x86/pic.h b/kern/arch/x86/pic.h
new file mode 100644 (file)
index 0000000..18bd78b
--- /dev/null
@@ -0,0 +1,43 @@
+/* Copyright (c) 2009, 2014 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * PIC: 8259 interrupt controller */
+
+#ifndef ROS_KERN_ARCH_PIC_H
+#define ROS_KERN_ARCH_PIC_H
+
+#include <ros/common.h>
+
+/* PIC (8259A)
+ * When looking at the specs, A0 is our CMD line, and A1 is the DATA line.  This
+ * means that blindly writing to PIC1_DATA is an OCW1 (interrupt masks).  When
+ * writing to CMD (A0), the chip can determine betweeb OCW2 and OCW3 by the
+ * setting of a few specific bits (OCW2 has bit 3 unset, OCW3 has it set). */
+#define PIC1_CMD                                       0x20
+#define PIC1_DATA                                      0x21
+#define PIC2_CMD                                       0xA0
+#define PIC2_DATA                                      0xA1
+// These are also hardcoded into the IRQ_HANDLERs of kern/trapentry.S
+#define PIC1_OFFSET                                    0x20
+#define PIC2_OFFSET                                    0x28
+#define PIC1_SPURIOUS                          (7 + PIC1_OFFSET)
+#define PIC2_SPURIOUS                          (7 + PIC2_OFFSET)
+#define PIC_EOI                                                0x20    /* OCW2 EOI */
+/* These set the next CMD read to return specific values.  Note that the chip
+ * remembers what setting we had before (IRR or ISR), if you do other reads of
+ * CMD. (not tested, written in the spec sheet) */
+#define PIC_READ_IRR                           0x0a    /* OCW3 irq ready next CMD read */
+#define PIC_READ_ISR                           0x0b    /* OCW3 irq service next CMD read */
+
+void pic_remap(void);
+void pic_mask_irq(int trap_nr);
+void pic_unmask_irq(int trap_nr);
+void pic_mask_all(void);
+uint16_t pic_get_mask(void);
+uint16_t pic_get_irr(void);
+uint16_t pic_get_isr(void);
+bool pic_check_spurious(int trap_nr);
+void pic_send_eoi(int trap_nr);
+
+#endif /* ROS_KERN_ARCH_PIC_H */
index c291ad6..1a925e5 100644 (file)
@@ -84,6 +84,7 @@
 #include <arch/mmu.h>
 #include <ros/trapframe.h>
 #include <arch/pci.h>
+#include <arch/pic.h>
 #include <arch/coreid.h>
 
 struct irq_handler {
index c36901b..808bfff 100644 (file)
@@ -19,7 +19,6 @@
 #include <string.h>
 #include <testing.h>
 #include <trap.h>
-#include <trap.h>
 #include <process.h>
 #include <syscall.h>
 #include <time.h>