Helper for registering device IRQs
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 23 Oct 2013 05:19:58 +0000 (22:19 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jan 2014 19:14:15 +0000 (11:14 -0800)
This puts all the dirty hacks into one place, without drivers needing to
know about the particulars of IRQ routing, which interrupt handler table
to use, etc.

kern/arch/riscv/trap.c
kern/arch/x86/pci.c
kern/arch/x86/pci.h
kern/arch/x86/smp.h
kern/arch/x86/trap.c
kern/arch/x86/trap.h
kern/include/trap.h
kern/src/testing.c

index e35534f..28598e3 100644 (file)
@@ -348,3 +348,15 @@ handle_trap(struct hw_trapframe *hw_tf)
 void send_nmi(uint32_t os_coreid)
 {
 }
+
+void register_interrupt_handler(handler_t table[], uint8_t int_num,
+                                poly_isr_t handler, void *data)
+{
+       printk("%s not implemented\n", __FUNCTION);
+}
+
+int register_dev_irq(int irq, void (*handler)(struct hw_trapframe *, void *),
+                     void *irq_arg)
+{
+       printk("%s not implemented\n", __FUNCTION);
+}
index 83f4207..5f68878 100644 (file)
@@ -6,16 +6,13 @@
 
 #include <arch/x86.h>
 #include <arch/pci.h>
+#include <trap.h>
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
 #include <kmalloc.h>
 #include <arch/pci_defs.h>
 
-/* Which pci devices hang off of which irqs */
-/* TODO: make this an array of SLISTs (pain from ioapic.c, etc...) */
-struct pci_device *irq_pci_map[NUM_IRQS] = {0};
-
 /* List of all discovered devices */
 struct pcidev_stailq pci_devices = STAILQ_HEAD_INITIALIZER(pci_devices);
 
index 9e40487..18c28e4 100644 (file)
 #define PCI_MAX_DEV                    32
 #define PCI_MAX_FUNC           8
 
-// Offset used for indexing IRQs. Why isnt this defined elsewhere?
-#define NUM_IRQS                       256
-#define KERNEL_IRQ_OFFSET      32
-
 // Run the PCI Code to loop over the PCI BARs. For now we don't use the BARs,
 // dont check em.
 #define CHECK_BARS                     0
@@ -171,8 +167,6 @@ struct pci_device {
 STAILQ_HEAD(pcidev_stailq, pci_device);
 SLIST_HEAD(pcidev_slist, pci_device);
 extern struct pcidev_stailq pci_devices;
-/* Mapping of irq -> PCI device (TODO: make this PCI-agnostic) */
-extern struct pci_device *irq_pci_map[NUM_IRQS];
 
 void pci_init(void);
 void pcidev_print_info(struct pci_device *pcidev, int verbosity);
index 6a7194d..62da4eb 100644 (file)
@@ -12,8 +12,6 @@
 // be careful changing this, esp if you go over 16
 #define NUM_HANDLER_WRAPPERS           5
 
-#define NUM_INTERRUPT_HANDLERS 256
-
 struct HandlerWrapper {
        checklist_t* cpu_list;
        uint8_t vector;
index dd1ac6b..485706e 100644 (file)
@@ -31,7 +31,11 @@ pseudodesc_t idt_pd;
 /* global handler table, used by core0 (for now).  allows the registration
  * of functions to be called when servicing an interrupt.  other cores
  * can set up their own later. */
-handler_t interrupt_handlers[NUM_INTERRUPT_HANDLERS];
+handler_t interrupt_handlers[NUM_IRQS];
+
+/* Which pci devices hang off of which irqs */
+/* TODO: make this an array of SLISTs (pain from ioapic.c, etc...) */
+struct pci_device *irq_pci_map[NUM_IRQS] = {0};
 
 const char *x86_trapname(int trapno)
 {
@@ -510,6 +514,26 @@ register_interrupt_handler(handler_t TP(TV(t)) table[],
        table[int_num].data = data;
 }
 
+int register_dev_irq(int irq, void (*handler)(struct hw_trapframe *, void *),
+                     void *irq_arg)
+{
+       register_interrupt_handler(interrupt_handlers,
+                                  KERNEL_IRQ_OFFSET + irq, handler, irq_arg);
+
+       /* TODO: whenever we sort out the ACPI/IOAPIC business, we'll probably want
+        * a helper to reroute an irq? */
+#ifdef CONFIG_ENABLE_MPTABLES
+       /* TODO: this should be for any IOAPIC EOI, not just MPTABLES */
+       /* Just sending to core 0 for now */
+       ioapic_route_irq(irq, 0);
+#else
+       pic_unmask_irq(irq);
+       unmask_lapic_lvt(LAPIC_LVT_LINT0);
+       enable_irq();
+#endif
+       return 0;
+}
+
 /* It's a moderate pain in the ass to put these in bit-specific files (header
  * hell with the set_current_ helpers) */
 #ifdef CONFIG_X86_64
index 76f8992..4ba0239 100644 (file)
@@ -5,6 +5,9 @@
 #define MSR_IA32_SYSENTER_ESP 0x175
 #define MSR_IA32_SYSENTER_EIP 0x176
 
+#define NUM_IRQS                                       256
+#define KERNEL_IRQ_OFFSET                      32
+
 // Trap numbers
 // These are processor defined:
 #define T_DIVIDE     0         // divide error
 #include <ros/common.h>
 #include <arch/mmu.h>
 #include <ros/trapframe.h>
+#include <arch/pci.h>
 
 /* The kernel's interrupt descriptor table */
 extern gatedesc_t idt[];
 extern pseudodesc_t idt_pd;
 extern taskstate_t ts;
+/* Mapping of irq -> PCI device (TODO: make this PCI-agnostic) */
+extern struct pci_device *irq_pci_map[NUM_IRQS];
 extern const char *x86_trapname(int trapno);
 extern void sysenter_handler(void);
 void backtrace_kframe(struct hw_trapframe *hw_tf);
index 2d79ddd..ecd51a5 100644 (file)
@@ -20,10 +20,11 @@ typedef struct InterruptHandler {
 extern handler_t interrupt_handlers[];
 
 void idt_init(void);
-void
-register_interrupt_handler(handler_t SSOMELOCK (CT(NUM_INTERRUPT_HANDLERS)table)[],
-                           uint8_t int_num,
-                           poly_isr_t handler, TV(t) data);
+void register_interrupt_handler(handler_t table[],
+                                uint8_t int_num,
+                                poly_isr_t handler, void *data);
+int register_dev_irq(int irq, void (*handler)(struct hw_trapframe *, void *),
+                     void *irq_arg);
 void print_trapframe(struct hw_trapframe *hw_tf);
 void page_fault_handler(struct hw_trapframe *hw_tf);
 /* Generic per-core timer interrupt handler.  set_percore_timer() will fire the
index 3a35baf..d3b449c 100644 (file)
@@ -50,7 +50,7 @@
 
 void test_ipi_sending(void)
 {
-       extern handler_t (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
+       extern handler_t interrupt_handlers[];
        int8_t state = 0;
 
        register_interrupt_handler(interrupt_handlers, I_TESTING,