rework external irq system, introduce hierarchical irq
authorLunaixsky <lunaixsky@qq.com>
Sun, 8 Dec 2024 15:41:35 +0000 (15:41 +0000)
committerLunaixsky <lunaixsky@qq.com>
Sun, 8 Dec 2024 15:41:35 +0000 (15:41 +0000)
30 files changed:
lunaix-os/arch/generic/includes/asm-generic/isrm.h
lunaix-os/arch/x86/exceptions/intr_routines.c
lunaix-os/arch/x86/exceptions/isrm.c
lunaix-os/arch/x86/hal/LBuild
lunaix-os/arch/x86/hal/apic.c
lunaix-os/arch/x86/hal/ioapic.c [deleted file]
lunaix-os/arch/x86/hal/mc146818a.c
lunaix-os/arch/x86/hal/ps2kbd.c
lunaix-os/arch/x86/includes/asm/soc/apic.h
lunaix-os/arch/x86/includes/asm/soc/ioapic.h [deleted file]
lunaix-os/arch/x86/includes/asm/x86_isrm.h
lunaix-os/hal/LBuild
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/ahci_pci.c
lunaix-os/hal/ahci/io_event.c
lunaix-os/hal/bus/pci.c
lunaix-os/hal/char/uart/16x50.h
lunaix-os/hal/char/uart/16x50_base.c
lunaix-os/hal/char/uart/16x50_isa.c
lunaix-os/hal/char/uart/16x50_pci.c
lunaix-os/hal/irq.c [new file with mode: 0644]
lunaix-os/includes/hal/ahci/ahci.h
lunaix-os/includes/hal/devtree.h
lunaix-os/includes/hal/devtreem.h
lunaix-os/includes/hal/irq.h [new file with mode: 0644]
lunaix-os/includes/hal/pci.h
lunaix-os/includes/listings/changeling.lst
lunaix-os/includes/listings/device_potens.lst
lunaix-os/includes/lunaix/device.h
lunaix-os/kernel/process/sched.c

index 0d4a15a5ed11e824807f0faec1be4996e8482557..5f82acafad6b7471e271a70051897d1f595885bb 100644 (file)
 
 typedef void (*isr_cb)(const struct hart_state*);
 
-typedef struct {
-    ptr_t msi_addr;
-    reg_t msi_data;
-    int mapped_iv;
-} msi_vector_t;
-#define msi_addr(msiv)   ((msiv).msi_addr)
-#define msi_data(msiv)   ((msiv).msi_data)
-#define msi_vect(msiv)   ((msiv).mapped_iv)
-
-typedef void* msienv_t;
-
 void
 isrm_init();
 
-/**
- * @brief Release a iv resource
- *
- * @param iv
- */
-void
-isrm_ivfree(int iv);
-
-/**
- * @brief Begin MSI allocation for given device
- *
- * @param iv
- */
-msienv_t
-isrm_msi_start(struct device* dev);
-
-/**
- * @brief Query number of msi avaliable for the device
- */
-int
-isrm_msi_avaliable(msienv_t msienv);
-
-/**
- * @brief Allocate a msi resource within defined msi resource list
- *        for the device, indexed by `index`
- */
-msi_vector_t
-isrm_msi_alloc(msienv_t msienv, cpu_t cpu, int index, isr_cb handler);
-
-/**
- * @brief Set the sideband information will be used for upcoming
- *        allocations
- */
-void
-isrm_msi_set_sideband(msienv_t msienv, ptr_t sideband);
-
-/**
- * @brief Done MSI allocation
- */
-void
-isrm_msi_done(msienv_t msienv);
-
-static inline must_inline msi_vector_t
-isrm_msi_alloc_simple(struct device* dev, cpu_t cpu, isr_cb handler)
-{   
-    msi_vector_t v;
-    msienv_t env;
-
-    env = isrm_msi_start(dev);
-    v = isrm_msi_alloc(env, cpu, 0, handler);
-    isrm_msi_done(env);
-
-    return v;
-}
-
-/**
- * @brief Bind the iv according to given device tree node
- *
- * @param node
- */
-int
-isrm_bind_dtn(struct dtn_intr* node);
-
-/**
- * @brief Get the handler associated with the given iv
- *
- * @param iv
- * @return isr_cb
- */
-isr_cb
-isrm_get(int iv);
-
-ptr_t
-isrm_get_payload(const struct hart_state*);
-
-void
-isrm_set_payload(int iv, ptr_t);
-
 /**
  * @brief Notify end of interrupt event
  *
@@ -119,12 +30,4 @@ isrm_set_payload(int iv, ptr_t);
 void
 isrm_notify_eoi(cpu_t id, int iv);
 
-/**
- * @brief Notify end of scheduling event
- *
- * @param id
- */
-void
-isrm_notify_eos(cpu_t id);
-
 #endif /* __LUNAIX_ISRM_H */
index 5e18496f9a630700f1e14deb6401dd086f206c2f..9410f7633e1aa226fc8b768dc600781e84da7a01 100644 (file)
@@ -75,16 +75,14 @@ intr_routine_apic_spi(const struct hart_state* state)
 void
 intr_routine_apic_error(const struct hart_state* state)
 {
-    u32_t error_reg = apic_read_reg(APIC_ESR);
-    char buf[32];
-    ksprintf(buf, "APIC error, ESR=0x%x", error_reg);
-
+    ERROR("APIC error");
     failsafe_diagnostic();
 }
 
 void
 intr_routine_sched(const struct hart_state* state)
 {
+    isrm_notify_eoi(0, LUNAIX_SCHED);
     schedule();
 }
 
index 86eec04593d45652d8cdae9885e01fe820be80b5..cd2d81bd6bb76578e5f37905521be8ffcf6340bb 100644 (file)
@@ -1,9 +1,7 @@
 #include <lunaix/spike.h>
-#include <lunaix/device.h>
 #include <asm/x86_isrm.h>
 
 #include "asm/x86.h"
-#include "asm/soc/ioapic.h"
 #include "asm/soc/apic.h"
 
 /*
@@ -17,8 +15,6 @@ static char iv_bmp[(IV_EX_END - IV_BASE_END) / 8];
 static isr_cb handlers[TOTAL_IV];
 static ptr_t ivhand_payload[TOTAL_IV];
 
-static struct x86_intc arch_intc_ctx;
-
 extern void
 intr_routine_fallback(const struct hart_state* state);
 
@@ -95,21 +91,6 @@ isrm_ivfree(int iv)
     handlers[iv] = intr_routine_fallback;
 }
 
-int
-isrm_bindirq(int irq, isr_cb irq_handler)
-{
-    int iv;
-    if (!(iv = isrm_ivexalloc(irq_handler))) {
-        fail("out of IV resource.");
-        return 0; // never reach
-    }
-
-    // fixed, edge trigged, polarity=high
-    isrm_irq_attach(irq, iv, 0, IRQ_DEFAULT);
-
-    return iv;
-}
-
 void
 isrm_bindiv(int iv, isr_cb handler)
 {
@@ -145,95 +126,4 @@ isrm_set_payload(int iv, ptr_t payload)
     assert(iv < 256);
 
     ivhand_payload[iv] = payload;
-}
-
-void
-isrm_irq_attach(int irq, int iv, cpu_t dest, u32_t flags)
-{
-    arch_intc_ctx.irq_attach(&arch_intc_ctx, irq, iv, dest, flags);
-}
-
-void
-isrm_notify_eoi(cpu_t id, int iv)
-{
-    arch_intc_ctx.notify_eoi(&arch_intc_ctx, id, iv);
-}
-
-void
-isrm_notify_eos(cpu_t id)
-{
-    isrm_notify_eoi(id, LUNAIX_SCHED);
-}
-
-msienv_t
-isrm_msi_start(struct device* dev)
-{
-    /*
-     *  In x86, the MSI topology is rather simple, as the only
-     *  source is the PCI itself, and the write destination is
-     *  explictly defined in specification, so we don't need the
-     *  msienv to hold dynamically probed address
-     */
-    return NULL;
-}
-
-int
-isrm_msi_avaliable(msienv_t msienv)
-{
-    return 1;
-}
-
-msi_vector_t
-isrm_msi_alloc(msienv_t msienv, cpu_t cpu, int index, isr_cb handler)
-{
-    unsigned int iv = isrm_ivexalloc(handler);
-
-    // we ignore the cpu redirection for now.
-    return (msi_vector_t){ 
-        .msi_addr  = __APIC_BASE_PADDR,
-        .msi_data  = iv,
-        .mapped_iv = iv
-    };
-}
-
-void
-isrm_msi_set_sideband(msienv_t msienv, ptr_t sideband)
-{
-    return;
-}
-
-void
-isrm_msi_done(msienv_t msienv)
-{
-    return;
-}
-
-
-
-int
-isrm_bind_dtn(struct dtn_intr* node)
-{
-    fail("not supported");
-}
-
-
-static int
-__intc_create(struct device_def* devdef, morph_t* obj)
-{
-    apic_init();
-    ioapic_init();
-
-    arch_intc_ctx.name = "i386_apic";
-    arch_intc_ctx.irq_attach = ioapic_irq_remap;
-    arch_intc_ctx.notify_eoi = apic_on_eoi;
-
-    return 0;
-}
-
-
-static struct device_def i386_intc = {
-    def_device_class(INTEL, CFG, INTC),
-    def_device_name("i386 apic"),
-    def_on_create(__intc_create)
-};
-EXPORT_DEVICE(i386_intc, &i386_intc, load_sysconf);
\ No newline at end of file
+}
\ No newline at end of file
index f3a3cae2abf28b9a22cdc2783f8c2407b8f139ef..870f743cf2a499f22421d02504d2c52712bc66ec 100644 (file)
@@ -4,7 +4,6 @@ sources([
     "cpu.c",
     "ps2kbd.c",
     "apic_timer.c",
-    "ioapic.c",
     "mc146818a.c",
     "pci.c"
 ])
\ No newline at end of file
index ddc2e31ef2471557122b8b6ddb4ab11d0b7b68bd..cd030969670e56d8c60ea3ba4a80a5bd75c8c29e 100644 (file)
 
 #include "asm/x86.h"
 #include "asm/x86_cpu.h"
-
 #include "asm/soc/apic.h"
+
 #include <asm/hart.h>
+#include <asm/x86_isrm.h>
 
 #include <lunaix/mm/mmio.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
+#include <lunaix/device.h>
+
+#include <hal/irq.h>
+#include <hal/acpi/acpi.h>
 
 #include "pic.h"
 
 LOG_MODULE("APIC")
 
+#define IOAPIC_IOREGSEL 0x00
+#define IOAPIC_IOWIN 0x10
+#define IOAPIC_IOREDTBL_BASE 0x10
+
+#define IOAPIC_REG_ID 0x00
+#define IOAPIC_REG_VER 0x01
+#define IOAPIC_REG_ARB 0x02
+
+#define IOAPIC_DELMOD_FIXED 0b000
+#define IOAPIC_DELMOD_LPRIO 0b001
+#define IOAPIC_DELMOD_NMI 0b100
+
+#define IOAPIC_MASKED (1 << 16)
+#define IOAPIC_TRIG_LEVEL (1 << 15)
+#define IOAPIC_INTPOL_L (1 << 13)
+#define IOAPIC_DESTMOD_LOGIC (1 << 11)
+
+#define IOAPIC_BASE_VADDR 0x2000
+
+#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL))
+#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN))
+
+
+#define LVT_ENTRY_LINT0(vector) (LVT_DELIVERY_FIXED | vector)
+
+// Pin LINT#1 is configured for relaying NMI, but we masked it here as I think
+//  it is too early for that
+// LINT#1 *must* be edge trigged (Intel manual vol3. 10-14)
+#define LVT_ENTRY_LINT1 (LVT_DELIVERY_NMI | LVT_MASKED | LVT_TRIGGER_EDGE)
+#define LVT_ENTRY_ERROR(vector) (LVT_DELIVERY_FIXED | vector)
+
+
+static volatile ptr_t _ioapic_base;
 static volatile ptr_t _apic_base;
 
 void
-apic_setup_lvts();
+apic_write_reg(unsigned int reg, unsigned int val)
+{
+    *(unsigned int*)(_apic_base + reg) = val;
+}
 
 void
+isrm_notify_eoi(cpu_t id, int iv)
+{
+    // for all external interrupts except the spurious interrupt
+    //  this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
+    if (iv >= IV_EX_BEGIN && iv != APIC_SPIV_IV) {
+        *(unsigned int*)(_apic_base + APIC_EOI) = 0;
+    }
+}
+
+unsigned int
+apic_read_reg(unsigned int reg)
+{
+    return *(unsigned int*)(_apic_base + (reg));
+}
+
+
+static void
+apic_setup_lvts()
+{
+    apic_write_reg(APIC_LVT_LINT0, LVT_ENTRY_LINT0(APIC_LINT0_IV));
+    apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1);
+    apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV));
+}
+
+static void
 apic_init()
 {
     // ensure that external interrupt is disabled
@@ -85,40 +151,117 @@ apic_init()
     apic_write_reg(APIC_SPIVR, spiv);
 }
 
-#define LVT_ENTRY_LINT0(vector) (LVT_DELIVERY_FIXED | vector)
+static void
+ioapic_init()
+{
+    acpi_context* acpi_ctx = acpi_get_context();
 
-// Pin LINT#1 is configured for relaying NMI, but we masked it here as I think
-//  it is too early for that
-// LINT#1 *must* be edge trigged (Intel manual vol3. 10-14)
-#define LVT_ENTRY_LINT1 (LVT_DELIVERY_NMI | LVT_MASKED | LVT_TRIGGER_EDGE)
-#define LVT_ENTRY_ERROR(vector) (LVT_DELIVERY_FIXED | vector)
+    _ioapic_base =
+        ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096);
+}
 
-void
-apic_setup_lvts()
+static void
+ioapic_write(u8_t sel, u32_t val)
 {
-    apic_write_reg(APIC_LVT_LINT0, LVT_ENTRY_LINT0(APIC_LINT0_IV));
-    apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1);
-    apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV));
+    IOAPIC_REG_SEL = sel;
+    IOAPIC_REG_WIN = val;
 }
 
-void
-apic_on_eoi(struct x86_intc* intc_ctx, cpu_t cpu, int iv)
+static u32_t
+ioapic_read(u8_t sel)
 {
-    // for all external interrupts except the spurious interrupt
-    //  this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
-    if (iv >= IV_EX_BEGIN && iv != APIC_SPIV_IV) {
-        *(unsigned int*)(_apic_base + APIC_EOI) = 0;
+    IOAPIC_REG_SEL = sel;
+    return IOAPIC_REG_WIN;
+}
+
+static void
+__ioapic_install_line(struct irq_domain *domain, irq_t irq)
+{
+    struct irq_line_wire *line;
+    u8_t reg_sel;
+    u32_t ioapic_fg;
+
+    line = irq->line;
+    reg_sel = IOAPIC_IOREDTBL_BASE + line->domain_mapped * 2;
+    ioapic_fg = IOAPIC_DELMOD_FIXED;
+
+    // Write low 32 bits
+    ioapic_write(reg_sel, (irq->vector | ioapic_fg) & 0x1FFFF);
+
+    // Write high 32 bits
+    ioapic_write(reg_sel + 1, 0);
+}
+
+static int
+__ioapic_translate_irq(struct irq_domain *domain, irq_t irq, void *irq_extra)
+{
+    struct irq_line_wire *line;
+
+    if (irq->type == IRQ_LINE) {
+        line = irq->line;
+        line->domain_mapped = acpi_gsimap(line->domain_local);
     }
+
+    return 0;
 }
 
-unsigned int
-apic_read_reg(unsigned int reg)
+static void
+__external_irq_dispatch(const struct hart_state* state)
 {
-    return *(unsigned int*)(_apic_base + (reg));
+    irq_t irq;
+
+    irq = irq_find(irq_get_default_domain(), hart_vector_stamp(state));
+
+    assert(irq);
+    irq_serve(irq, state);
 }
 
-void
-apic_write_reg(unsigned int reg, unsigned int val)
+static int
+__ioapic_install_irq(struct irq_domain *domain, irq_t irq)
 {
-    *(unsigned int*)(_apic_base + reg) = val;
-}
\ No newline at end of file
+    irq->vector = isrm_ivexalloc(__external_irq_dispatch);
+
+    if (irq->type == IRQ_MESSAGE) {
+        irq->msi->wr_addr = __APIC_BASE_PADDR;
+    }
+    else {
+        __ioapic_install_line(domain, irq);
+    }
+
+    irq_record(domain, irq);
+    
+    return 0;
+}
+
+
+static struct irq_domain_ops apic_domain_ops = {
+    .map_irq = __ioapic_translate_irq,
+    .install_irq = __ioapic_install_irq
+};
+
+static int
+apic_device_create(struct device_def* def, morph_t* morph)
+{
+    int err;
+    struct device* dev;
+    struct irq_domain* domain;
+
+    apic_init();
+    ioapic_init();
+
+    dev = device_allocsys(NULL, NULL);
+    domain = irq_create_domain(dev, &apic_domain_ops);
+
+    irq_set_default_domain(domain);
+    register_device(dev, &def->class, "apic");
+    irq_attach_domain(NULL, domain);
+    
+    return 0;
+}
+
+static struct device_def apic_devdef = {
+    def_device_class(INTEL, CFG, INTC),
+    def_device_name("x86 APIC"),
+    def_on_create(apic_device_create)
+};
+EXPORT_DEVICE(x86_apic, &apic_devdef, load_sysconf);
\ No newline at end of file
diff --git a/lunaix-os/arch/x86/hal/ioapic.c b/lunaix-os/arch/x86/hal/ioapic.c
deleted file mode 100644 (file)
index e03d4b5..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#include <hal/acpi/acpi.h>
-
-#include <lunaix/mm/mmio.h>
-
-#include <asm/hart.h>
-#include "asm/soc/ioapic.h"
-#include "asm/x86.h"
-
-#define IOAPIC_IOREGSEL 0x00
-#define IOAPIC_IOWIN 0x10
-#define IOAPIC_IOREDTBL_BASE 0x10
-
-#define IOAPIC_REG_ID 0x00
-#define IOAPIC_REG_VER 0x01
-#define IOAPIC_REG_ARB 0x02
-
-#define IOAPIC_DELMOD_FIXED 0b000
-#define IOAPIC_DELMOD_LPRIO 0b001
-#define IOAPIC_DELMOD_NMI 0b100
-
-#define IOAPIC_MASKED (1 << 16)
-#define IOAPIC_TRIG_LEVEL (1 << 15)
-#define IOAPIC_INTPOL_L (1 << 13)
-#define IOAPIC_DESTMOD_LOGIC (1 << 11)
-
-#define IOAPIC_BASE_VADDR 0x2000
-
-#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL))
-#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN))
-
-static volatile ptr_t _ioapic_base;
-
-void
-ioapic_init()
-{
-    // Remapping the IRQs
-
-    acpi_context* acpi_ctx = acpi_get_context();
-
-    _ioapic_base =
-        ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096);
-}
-
-void
-ioapic_write(u8_t sel, u32_t val)
-{
-    IOAPIC_REG_SEL = sel;
-    IOAPIC_REG_WIN = val;
-}
-
-u32_t
-ioapic_read(u8_t sel)
-{
-    IOAPIC_REG_SEL = sel;
-    return IOAPIC_REG_WIN;
-}
-
-void
-ioapic_irq_remap(struct x86_intc* intc, int irq, int iv, cpu_t dest, u32_t flags)
-{
-    /*
-        FIXME move it to HAL level. since every platform might have their own
-       wiring, thus gsi mapping is required all the time
-    */
-    irq = acpi_gsimap(irq);
-    u8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2;
-
-    u32_t ioapic_fg = 0;
-
-    if ((flags & IRQ_TYPE) == IRQ_TYPE_FIXED) {
-        ioapic_fg |= IOAPIC_DELMOD_FIXED;
-    } else {
-        ioapic_fg |= IOAPIC_DELMOD_NMI;
-    }
-
-    if ((flags & IRQ_TRIG_LEVEL)) {
-        ioapic_fg |= IOAPIC_TRIG_LEVEL;
-    }
-
-    if (!(flags & IRQ_VE_HI)) {
-        ioapic_fg |= IOAPIC_INTPOL_L;
-    }
-
-    // Write low 32 bits
-    ioapic_write(reg_sel, (iv | ioapic_fg) & 0x1FFFF);
-
-    // Write high 32 bits
-    ioapic_write(reg_sel + 1, (dest << 24));
-}
\ No newline at end of file
index f5bc285b2425a579c8eceb8eddf74621688530ea..ec2cd4b34f122a9499d424131bfb29a84db34bfe 100644 (file)
@@ -15,6 +15,7 @@
 #include <lunaix/hart_state.h>
 
 #include <hal/hwrtc.h>
+#include <hal/irq.h>
 
 #include <klibc/string.h>
 
@@ -57,7 +58,7 @@
 struct mc146818
 {
     struct hwrtc_potens* rtc_context;
-    u32_t rtc_iv;
+    irq_t irq;
 };
 
 #define rtc_state(data) ((struct mc146818*)(data))
@@ -132,10 +133,11 @@ rtc_setwalltime(struct hwrtc_potens* rtc, datetime_t* datetime)
 }
 
 static void
-__rtc_tick(const struct hart_state* hstate)
+__rtc_tick(irq_t irq, const struct hart_state* hstate)
 {
-    struct mc146818* state = (struct mc146818*)isrm_get_payload(hstate);
+    struct mc146818* state;
 
+    state = irq_payload(irq, struct mc146818);
     state->rtc_context->live++;
 
     (void)rtc_read_reg(RTC_REG_C);
@@ -164,8 +166,12 @@ static int
 __rtc_calibrate(struct hwrtc_potens* pot)
 {
     struct mc146818* state;
+    struct device* rtc_dev;
+    u8_t reg;
+
+    rtc_dev = potens_dev(pot);
 
-    u8_t reg = rtc_read_reg(RTC_REG_A);
+    reg = rtc_read_reg(RTC_REG_A);
     reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ;
     rtc_write_reg(RTC_REG_A, reg);
 
@@ -177,9 +183,12 @@ __rtc_calibrate(struct hwrtc_potens* pot)
 
     pot->base_freq = RTC_TIMER_BASE_FREQUENCY;
 
-    state = (struct mc146818*)potens_dev(pot)->underlay;
-    state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick);
-    isrm_set_payload(state->rtc_iv, __ptr(state));
+    state = (struct mc146818*)rtc_dev->underlay;
+
+    state->irq = irq_declare_line(__rtc_tick, PC_AT_IRQ_RTC, NULL);
+    irq_set_payload(state->irq, state);
+
+    irq_assign(irq_owning_domain(rtc_dev), state->irq);
 
     return 0;
 }
index ee4a67e0f99855acb884cd8fc5b87fe386ddcea6..8799da2302dcbda7efbb9be09d82a51e1b0085d7 100644 (file)
@@ -6,6 +6,8 @@
 #include <lunaix/timer.h>
 #include <lunaix/hart_state.h>
 
+#include <hal/irq.h>
+
 #include "asm/x86.h"
 
 #include <klibc/string.h>
@@ -189,7 +191,7 @@ static struct input_device* kbd_idev;
 // #define KBD_DBGLOG
 
 static void
-intr_ps2_kbd_handler(const struct hart_state* hstate);
+intr_ps2_kbd_handler(irq_t irq, const struct hart_state* hstate);
 
 static u8_t
 ps2_issue_cmd_wretry(char cmd, u16_t arg);
@@ -309,7 +311,9 @@ ps2_kbd_create(struct device_def* devdef, morph_t* obj)
      *
      *  所以,保险的方法是:在初始化后才去设置ioapic,这样一来我们就能有一个稳定的IRQ#1以放心使用。
      */
-    isrm_bindirq(PC_AT_IRQ_KBD, intr_ps2_kbd_handler);
+    
+    irq_t irq = irq_declare_line(intr_ps2_kbd_handler, PC_AT_IRQ_KBD, NULL);    
+    irq_assign(irq_owning_domain(kbd_idev->dev_if), irq);
 
     return 0;
 
@@ -401,7 +405,7 @@ kbd_buffer_key_event(kbd_keycode_t key, u8_t scancode, kbd_kstate_t state)
 }
 
 static void
-intr_ps2_kbd_handler(const struct hart_state* hstate)
+intr_ps2_kbd_handler(irq_t irq, const struct hart_state* hstate)
 {
 
     // This is important! Don't believe me? try comment it out and run on Bochs!
index 40c395cee55619389d7e57d29c5074df2ad7c59e..83ad3ed2bbace3d02c36d3690243b7a240c9c6c8 100644 (file)
@@ -72,10 +72,4 @@ apic_read_reg(unsigned int reg);
 void
 apic_write_reg(unsigned int reg, unsigned int val);
 
-void
-apic_init();
-
-void
-apic_on_eoi(struct x86_intc* intc_ctx, cpu_t cpu, int iv);
-
 #endif /* __LUNAIX_APIC_H */
diff --git a/lunaix-os/arch/x86/includes/asm/soc/ioapic.h b/lunaix-os/arch/x86/includes/asm/soc/ioapic.h
deleted file mode 100644 (file)
index d87ab18..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __LUNAIX_IOAPIC_H
-#define __LUNAIX_IOAPIC_H
-
-#include "asm/x86.h"
-
-void
-ioapic_init();
-
-void
-ioapic_irq_remap(struct x86_intc*,
-                 int irq,
-                 int iv,
-                 cpu_t dest,
-                 u32_t flags);
-
-#endif /* __LUNAIX_IOAPIC_H */
index b48608017342e060b2a83bbeac7c756ddd7afd6d..4d6fb4444d2c69e533ae1e4741e23cfc67457c32 100644 (file)
@@ -3,14 +3,6 @@
 
 #include <asm-generic/isrm.h>
 
-/**
- * @brief Bind a given irq and associated handler to an iv
- *
- * @param iv iv allocated by system
- */
-int
-isrm_bindirq(int irq, isr_cb irq_handler);
-
 /**
  * @brief Bind given iv with it's associated handler
  *
@@ -39,4 +31,28 @@ isrm_ivosalloc(isr_cb handler);
 int
 isrm_ivexalloc(isr_cb handler);
 
+/**
+ * @brief Release a iv resource
+ *
+ * @param iv
+ */
+void
+isrm_ivfree(int iv);
+
+/**
+ * @brief Get the handler associated with the given iv
+ *
+ * @param iv
+ * @return isr_cb
+ */
+isr_cb
+isrm_get(int iv);
+
+ptr_t
+isrm_get_payload(const struct hart_state*);
+
+void
+isrm_set_payload(int iv, ptr_t);
+
+
 #endif /* __LUNAIX_X86_ISRM_H */
index 673a8fcdc7191102b0211ac38878a3585ab94628..6ff2713d2e5de227f582fd588ce6b683e671e035 100644 (file)
@@ -8,4 +8,8 @@ use("timer")
 use("bus")
 
 if config("use_devicetree"):
-    use("devtree")
\ No newline at end of file
+    use("devtree")
+
+sources([
+    "irq.c"
+])
\ No newline at end of file
index 04a71047b6708f4f06e8a3465a4900aead0acd88..7d0b9b2396c18ee9447313e34e72a4afe1b0330a 100644 (file)
@@ -35,7 +35,7 @@
 
 LOG_MODULE("AHCI")
 
-DEFINE_LLIST(ahcis);
+static DEFINE_LLIST(ahcis);
 
 static char sata_ifs[][20] = { "Not detected",
                                "SATA I (1.5Gbps)",
@@ -80,10 +80,9 @@ ahci_driver_init(struct ahci_driver_param* param)
 {
     struct ahci_driver* ahci_drv = vzalloc(sizeof(*ahci_drv));
     struct ahci_hba* hba = &ahci_drv->hba;
-    ahci_drv->id = param->ahci_iv;
-
-    isrm_set_payload(param->ahci_iv, (ptr_t)&ahcis);
+    ahci_drv->id = param->irq->vector;
 
+    irq_set_payload(param->irq, &ahcis);
     llist_append(&ahcis, &ahci_drv->ahci_drvs);
 
     hba->base = (hba_reg_t*)ioremap(param->mmio_base, param->mmio_size);
index 4435da12431ddc6a451f716664a02dcfcbf0c156..6c4fddebaf18a681c92faa6533d68e02e1cca06b 100644 (file)
@@ -11,7 +11,7 @@ ahci_pci_create(struct device_def* def, morph_t* morphed)
     struct device* dev;
     struct pci_base_addr* bar6;
     struct ahci_driver* ahci_drv;
-    msi_vector_t msiv;
+    irq_t irq;
 
     probe = changeling_try_reveal(morphed, pci_probe_morpher);
     if (!probe) {
@@ -29,12 +29,13 @@ ahci_pci_create(struct device_def* def, morph_t* morphed)
     
     assert(pci_capability_msi(probe));
 
-    msiv = pci_msi_setup_simple(probe, ahci_hba_isr);
+    irq = pci_declare_msi_irq(ahci_hba_isr, probe, NULL);
+    pci_assign_msi(probe, irq);
 
     struct ahci_driver_param param = {
         .mmio_base = bar6->start,
         .mmio_size = bar6->size,
-        .ahci_iv = msi_vect(msiv),
+        .irq = irq,
     };
 
     ahci_drv = ahci_driver_init(&param);
index 608634d84e5fdbd52151441380a4ea099ee55e5f..c40a85c3947e095ebfcb47e81a81bc567c8504b2 100644 (file)
@@ -7,12 +7,13 @@
 LOG_MODULE("io_evt")
 
 void
-ahci_hba_isr(const struct hart_state* hstate)
+ahci_hba_isr(irq_t irq, const struct hart_state* hstate)
 {
     struct ahci_hba* hba;
     struct ahci_driver *pos, *n;
-    struct llist_header* ahcis = (struct llist_header*)isrm_get_payload(hstate);
+    struct llist_header* ahcis;
 
+    ahcis = irq_payload(irq, struct llist_header);
     llist_for_each(pos, n, ahcis, ahci_drvs)
     {
         if (pos->id == hart_vector_stamp(hstate)) {
index 3052a90eea05bc70b5128d41d96f90682ea6c218..3e940e0b006a6a7e7c4a1f0c95e1add6ac3a6536 100644 (file)
@@ -107,6 +107,7 @@ __pci_add_prober(pciaddr_t loc, ptr_t pci_base, int devinfo)
     prober->cspace_base = pci_base;
     prober->intr_info = intr;
     prober->loc = loc;
+    prober->irq_domain = irq_get_domain(pci_bridge);
 
     changeling_morph_anon(pci_probers, prober->mobj, pci_probe_morpher);
 
@@ -271,12 +272,12 @@ pci_scan()
 }
 
 static void
-__pci_config_msi(struct pci_probe* probe, msi_vector_t msiv)
+__pci_config_msi(struct pci_probe* probe, irq_t irq)
 {
     // PCI LB Spec. (Rev 3) Section 6.8 & 6.8.1
 
-    ptr_t msi_addr = msi_addr(msiv);
-    u32_t msi_data = msi_data(msiv);
+    ptr_t msi_addr = irq->msi->wr_addr;
+    u32_t msi_data = irq->msi->message;
 
     pci_reg_t reg1 = pci_read_cspace(probe->cspace_base, probe->msi_loc);
     pci_reg_t msg_ctl = reg1 >> 16;
@@ -306,39 +307,27 @@ __pci_config_msi(struct pci_probe* probe, msi_vector_t msiv)
     pci_write_cspace(probe->cspace_base, probe->msi_loc, reg1);
 }
 
-msienv_t
-pci_msi_start(struct pci_probe* probe)
+irq_t
+pci_declare_msi_irq(irq_servant callback, 
+                    struct pci_probe* probe, void *irq_extra)
 {
-    /*
-        As a PCI bridge/root complex can be initialised from device tree node,
-        in that case, general information such as routing, rid remapping, 
-        are vital to all msi setup of all peripherals under it.
-
-        Therefore, a wrapper around isrm_msi_* is needed in order to
-        improve overall readability and usability, where the bridge
-        device instance that contain these information will be 
-        automatically passed to the underlay as credential to perform
-        configuration.
-    */
-
-    msienv_t env;
-    
-    env = isrm_msi_start(pci_bridge);
-    isrm_msi_set_sideband(env, pci_requester_id(probe));
-
-    return env;
+    return irq_declare_msg(callback, probe->loc, probe->loc, irq_extra);
 }
 
-msi_vector_t
-pci_msi_setup_at(msienv_t msienv, struct pci_probe* probe, 
-                 int i, isr_cb handler)
+int
+pci_assign_msi(struct pci_probe* probe, irq_t irq)
 {
-    msi_vector_t msiv;
+    int err = 0;
 
-    msiv = isrm_msi_alloc(msienv, 0, i, handler);
-    __pci_config_msi(probe, msiv);
+    assert(irq->type == IRQ_MESSAGE);
 
-    return msiv;
+    err = irq_assign(probe->irq_domain, irq);
+    if (err) {
+        return err;
+    }
+
+    __pci_config_msi(probe, irq);
+    return 0;
 }
 
 size_t
@@ -532,6 +521,29 @@ EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping);
 
 /*---------- PCI 3.0 HBA device definition ----------*/
 
+static int
+__pci_irq_install(struct irq_domain* domain, irq_t irq)
+{
+    struct irq_domain* parent;
+    int err;
+
+    parent = domain->parent;
+    err = parent->ops->install_irq(parent, irq);
+    if (err) {
+        return err;
+    }
+
+    if (irq->type == IRQ_MESSAGE) {
+        irq->msi->message = irq->vector;
+    }
+
+    return 0;
+}
+
+static struct irq_domain_ops pci_irq_ops = {
+    .install_irq = __pci_irq_install
+};
+
 static int
 pci_register(struct device_def* def)
 {
@@ -543,15 +555,19 @@ pci_register(struct device_def* def)
 static int
 pci_create(struct device_def* def, morph_t* obj)
 {
-    devtree_link_t devtree_node;
+    struct irq_domain *pci_domain;
+    pci_bridge = device_allocsys(NULL, NULL);
 
+#ifdef CONFIG_USE_DEVICETREE
+    devtree_link_t devtree_node;
     devtree_node = changeling_try_reveal(obj, dt_node_morpher);
-
-    pci_bridge = device_allocsys(NULL, NULL);
     device_set_devtree_node(pci_bridge, devtree_node);
+#endif
 
-    register_device(pci_bridge, &def->class, "pci_bridge");
+    pci_domain = irq_create_domain(pci_bridge, &pci_irq_ops);
+    irq_attach_domain(irq_get_default_domain(), pci_domain);
 
+    register_device(pci_bridge, &def->class, "pci_bridge");
     pci_scan();
 
     return 0;
@@ -564,4 +580,4 @@ static struct device_def pci_def = {
     def_on_register(pci_register),
     def_on_create(pci_create)
 };
-EXPORT_DEVICE(pci3hba, &pci_def, load_sysconf);
+EXPORT_DEVICE(pci3hba, &pci_def, load_onboot);
index 40ebe94a421a7cda1fa47cb1d87ba9af175f6abb..4a2c8a5b61e9b6012b380ffbd68db82fdfbf076d 100644 (file)
@@ -2,6 +2,7 @@
 #define __LUNAIX_16550_H
 
 #include <hal/serial.h>
+#include <hal/irq.h>
 #include <lunaix/types.h>
 
 #define UART_rRxTX 0
@@ -70,7 +71,7 @@ struct uart16550
     struct serial_dev* sdev;
     ptr_t base_addr;
     unsigned int base_clk;
-    int iv;
+    irq_t irq;
 
     struct
     {
@@ -227,10 +228,10 @@ int
 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len);
 
 void
-uart_handle_irq_overlap(int iv, struct llist_header* ports);
+uart_handle_irq_overlap(irq_t irq, struct llist_header* ports);
 
 void
-uart_handle_irq(int iv, struct uart16550 *uart);
+uart_handle_irq(irq_t irq, struct uart16550 *uart);
 
 static inline struct serial_dev*
 uart_create_serial(struct uart16550* uart, struct devclass* class, 
index 8b3930f29779973071d45facf65f4a56ece92f76..5b14445521c5c9f92345ee0caea9fe960da37998 100644 (file)
@@ -103,13 +103,13 @@ uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args)
 }
 
 void
-uart_handle_irq_overlap(int iv, struct llist_header* ports)
+uart_handle_irq_overlap(irq_t irq, struct llist_header* ports)
 {
     struct uart16550 *pos, *n;
     llist_for_each(pos, n, ports, local_ports)
     {
         int is = uart_intr_identify(pos);
-        if (iv == pos->iv && (is == UART_CHR_TIMEOUT)) {
+        if (irq == pos->irq && (is == UART_CHR_TIMEOUT)) {
             goto done;
         }
     }
@@ -117,11 +117,11 @@ uart_handle_irq_overlap(int iv, struct llist_header* ports)
     return;
 
 done:
-    uart_handle_irq(iv, pos);
+    uart_handle_irq(irq, pos);
 }
 
 void
-uart_handle_irq(int iv, struct uart16550 *uart)
+uart_handle_irq(irq_t irq, struct uart16550 *uart)
 {
     char tmpbuf[32];
     char recv;
index 39582236364660f4a1e21144eadf27a69ffd45ff..c24c1d008588ca5a5754ce8a49f8cae4669d43b4 100644 (file)
@@ -11,10 +11,9 @@ LOG_MODULE("16x50-isa");
 static DEFINE_LLIST(com_ports);
 
 static void
-com_irq_handler(const struct hart_state* hstate)
+com_irq_handler(irq_t irq, const struct hart_state* hstate)
 {
-    int vector = hart_vector_stamp(hstate);
-    uart_handle_irq_overlap(vector, &com_ports);
+    uart_handle_irq_overlap(irq, &com_ports);
 }
 
 int
@@ -25,6 +24,7 @@ isa16x50_create_once(struct device_def* def)
     int* irqs[] = { &irq4, &irq3, &irq4, &irq3 };
 
     struct uart16550* uart = NULL;
+    struct serial_dev* sdev;
     ptr_t base;
 
     // COM 1...4
@@ -37,20 +37,20 @@ isa16x50_create_once(struct device_def* def)
             continue;
         }
 
+        sdev = uart_create_serial(uart, &def->class, &com_ports, "S");
+        
         int irq = *irqs[i];
         if (irq) {
             /*
              *  Since these irqs are overlapped, this particular setup is needed
              * to avoid double-bind
              */
-            uart->iv = isrm_bindirq(irq, com_irq_handler);
+            uart->irq = irq_declare_line(com_irq_handler, irq, NULL);
+            irq_assign(irq_owning_domain(sdev->dev), uart->irq);
             *((volatile int*)irqs[i]) = 0;
         }
-
-        INFO("base: 0x%x, irq=%d", 
-                base, irq, uart->iv);
-
-        uart_create_serial(uart, &def->class, &com_ports, "S");
+        
+        INFO("base: 0x%x, irq=%d", base, irq);
     }
 
     return 0;
index 20beda12244206a04454e5e132c5b9cd18483d26..9de2396aafe6203e007f45ad69cbe644addc8ff7 100644 (file)
@@ -15,23 +15,14 @@ static DEFINE_LLIST(pci_ports);
 
 
 static void
-uart_msi_irq_handler(const struct hart_state* hstate)
+uart_msi_irq_handler(irq_t irq, const struct hart_state* hstate)
 {
-    int vector;
     struct uart16550* uart;
     
-    vector = hart_vector_stamp(hstate);
-    uart = (struct uart16550*)isrm_get_payload(hstate);
+    uart = irq_payload(irq, struct uart16550);
 
     assert(uart);
-    uart_handle_irq(vector, uart);
-}
-
-static void
-uart_intx_irq_handler(const struct hart_state* hstate)
-{
-    int vector = hart_vector_stamp(hstate);
-    uart_handle_irq_overlap(vector, &pci_ports);
+    uart_handle_irq(irq, uart);
 }
 
 static bool
@@ -56,7 +47,7 @@ pci16x50_pci_create(struct device_def* def, morph_t* obj)
     struct pci_probe* probe;
     struct uart16550* uart;
     struct serial_dev* sdev;
-    msi_vector_t msiv;
+    irq_t irq;
     
     probe = changeling_reveal(obj, pci_probe_morpher);
 
@@ -102,16 +93,16 @@ pci16x50_pci_create(struct device_def* def, morph_t* obj)
 
         sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI");
 
-        msiv = pci_msi_setup_simple(probe, uart_msi_irq_handler);
-        isrm_set_payload(msi_vect(msiv), __ptr(uart));
+        irq = pci_declare_msi_irq(uart_msi_irq_handler, probe, NULL);
+        irq_set_payload(irq, uart);
+        pci_assign_msi(probe, irq);
 
-        INFO("base: 0x%x (%s), irq=%d (%s)", 
+        INFO("base: 0x%x (%s), %s", 
                 bar->start, 
                 pci_bar_mmio_space(bar) ? "mmio" : "pmio",
-                msi_vect(msiv), 
                 pci_capability_msi(probe) ? "msi" : "intx, re-routed");
         
-        uart->iv = msi_vect(msiv);
+        uart->irq = irq;
 
         pci_bind_instance(probe, sdev->dev);
     }
diff --git a/lunaix-os/hal/irq.c b/lunaix-os/hal/irq.c
new file mode 100644 (file)
index 0000000..b4bc0ec
--- /dev/null
@@ -0,0 +1,195 @@
+#include <hal/irq.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/owloysius.h>
+
+static struct irq_domain* default_domain = NULL;
+static DEFINE_LLIST(irq_domains);
+
+static void
+__default_servant(irq_t irq, const struct hart_state* state)
+{
+    return;
+}
+
+struct irq_domain*
+irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops)
+{
+    struct irq_domain* domain;
+
+    assert(ops->install_irq);
+
+    domain = new_potens(potens(INT_DOMAIN), struct irq_domain);
+    device_grant_potens(intc_dev, potens_meta(domain));
+
+    btrie_init(&domain->irq_map, ilog2(8));
+    llist_append(&irq_domains, &domain->list);
+    domain->ops = ops;
+    
+    return domain;
+}
+
+struct irq_domain*
+irq_owning_domain(struct device* dev)
+{
+#ifdef CONFIG_USE_DEVICETREE
+    struct device* intc;
+    struct dtn* intr_parent;
+    struct potens_meta* domain_m;
+
+    intr_parent = dev->devtree_node->intr.parent;
+    intc = resolve_device_morph(dt_mobj(intr_parent));
+
+    if (!intc) {
+        return NULL;
+    }
+
+    domain_m = device_get_potens(intc, potens(INT_DOMAIN));
+    return !domain_m ?: get_potens(domain_m, struct irq_domain);
+#else
+    return default_domain;
+#endif
+}
+
+int
+irq_attach_domain(struct irq_domain* parent, struct irq_domain* child)
+{
+#ifndef CONFIG_USE_DEVICETREE
+    parent = parent ?: default_domain;
+    child->parent = parent;
+#endif
+    return 0;
+}
+
+static void
+__irq_create_line(irq_t irq, ptr_t local_int)
+{
+    struct irq_line_wire *line;
+
+    line = valloc(sizeof(*line));
+    line->domain_local = local_int;
+    line->domain_mapped = local_int;
+
+    irq->line = line;
+}
+
+static void
+__irq_create_msi(irq_t irq, ptr_t message)
+{
+    struct irq_msi_wire *msi;
+
+    msi = valloc(sizeof(*msi));
+    msi->message  = message;
+
+    irq->msi = msi;
+}
+
+irq_t
+irq_declare(enum irq_type type, irq_servant callback, 
+            ptr_t data, void* irq_extra)
+{
+    irq_t irq;
+
+    irq  = valloc(sizeof(*irq));
+    *irq = (struct irq_object) {
+        .type = type,
+        .serve = callback ?: __default_servant,
+        .irq_extra = irq_extra
+    };
+
+    if (type == IRQ_LINE) {
+        __irq_create_line(irq, data);
+    }
+
+    else if (type == IRQ_MESSAGE) {
+        __irq_create_msi(irq, data);
+    }
+
+    return irq;
+}
+
+void
+irq_revoke(irq_t irq)
+{
+    if (--(irq->ref) > 0) {
+        return;
+    }
+    vfree(irq);
+}
+
+int
+irq_assign(struct irq_domain* domain, irq_t irq)
+{
+    int err = 0;    
+    if (domain->ops->map_irq) {
+        err = domain->ops->map_irq(domain, irq, irq->irq_extra);
+        if (err) {
+            return err;
+        }
+    }
+
+    /*
+        A domain controller may choose to forward the interrupt
+        (i.e., irq became transparent and belongs to the higher domain)
+        We allow controller decide whether to record the irq under its wing
+    */
+    err = domain->ops->install_irq(domain, irq);
+    if (err) {
+        return err;
+    }
+
+    irq->domain = domain;
+    return 0;
+}
+
+irq_t
+irq_find(struct irq_domain* domain, int local_irq)
+{
+    irq_t irq = NULL;
+    struct irq_domain* current;
+
+    // Find recursively, in case of irq forwarding
+
+    current = domain ?: default_domain;
+    while (current && !irq) {
+        irq = (irq_t)btrie_get(&current->irq_map, local_irq);
+        current = irq_parent_domain(current);
+    }
+    
+    return irq;
+}
+
+void
+irq_record(struct irq_domain* domain, irq_t irq)
+{
+    irq->ref++;
+    btrie_set(&domain->irq_map, irq->vector, irq);
+}
+
+void
+irq_set_default_domain(struct irq_domain* domain)
+{
+    assert(!default_domain);
+    default_domain = domain;
+}
+
+int
+irq_forward_install(struct irq_domain* current, irq_t irq)
+{
+    struct irq_domain* parent;
+
+    parent = irq_parent_domain(current);
+
+    if (irq->type == IRQ_LINE) {
+        irq->line->domain_local = irq->line->domain_mapped;
+    }
+
+    irq->domain = parent;
+    return parent->ops->install_irq(parent, irq);
+}
+
+struct irq_domain*
+irq_get_default_domain()
+{
+    assert(default_domain);
+    return default_domain;
+}
index 7eaf10d4e012d73f231c457eeddf84a76f1cf57c..b55ba9581c2c09f2f2921347c84cc42c98735c00 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "hba.h"
 #include <asm-generic/isrm.h>
+#include <hal/irq.h>
 
 /*
  * Macro naming rule:
@@ -26,7 +27,7 @@ struct ahci_driver_param
 {
     ptr_t mmio_base;
     size_t mmio_size;
-    int ahci_iv;
+    irq_t irq;
 };
 
 void
@@ -59,6 +60,6 @@ struct ahci_driver*
 ahci_driver_init(struct ahci_driver_param* param);
 
 void
-ahci_hba_isr(const struct hart_state* hstate);
+ahci_hba_isr(irq_t irq, const struct hart_state* hstate);
 
 #endif /* __LUNAIX_AHCI_H */
index e7e0cf37ce0a32c36ece6877426e7db109ec8ab2..ae18e31983e89011f06a72960d7b216bc850a2d9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LUNAIX_DEVTREE_H
 #define __LUNAIX_DEVTREE_H
 
+#ifdef CONFIG_USE_DEVICETREE
 #include <lunaix/types.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/hstr.h>
@@ -727,4 +728,5 @@ dtpi_next_val(struct dtpropi* dtpi, struct dtp_val* val, int cells)
     return true;
 }
 
+#endif
 #endif /* __LUNAIX_DEVTREE_H */
index 2b0904d6babf6d257873d3a4eab4773d70032e1b..d235cd7f3375cc90c2cb0147bc31da927230f5e0 100644 (file)
@@ -13,7 +13,7 @@ struct device;
 
 typedef struct dtn* devtree_link_t;
 
-#define dt_node_morpher     morphable_attrs(dt_node, mobj)
+#define dt_node_morpher     morphable_attrs(dtn, mobj)
 
 struct dtm_driver_info
 {
diff --git a/lunaix-os/includes/hal/irq.h b/lunaix-os/includes/hal/irq.h
new file mode 100644 (file)
index 0000000..e592e22
--- /dev/null
@@ -0,0 +1,162 @@
+#ifndef __LUNAIX_IRQ_H
+#define __LUNAIX_IRQ_H
+
+#include <lunaix/changeling.h>
+#include <lunaix/device.h>
+#include <lunaix/ds/btrie.h>
+#include <asm/hart.h>
+
+struct irq_domain;
+typedef struct irq_object* irq_t;
+typedef void (*irq_servant)(irq_t, const struct hart_state*);
+
+struct irq_domain_ops
+{
+    int
+    (*install_irq)(struct irq_domain*, irq_t);
+
+    int
+    (*map_irq)(struct irq_domain*, irq_t, void* irq_extra);
+
+    int
+    (*remove_irq)(struct irq_domain*, irq_t);
+};
+
+struct irq_domain
+{
+    POTENS_META;
+
+    struct llist_header list;
+
+    struct irq_domain* parent;
+    struct btrie irq_map;
+    const struct irq_domain_ops* ops;
+    void* object;
+};
+
+enum irq_type
+{
+    IRQ_LINE,
+    IRQ_MESSAGE
+};
+
+struct irq_line_wire
+{
+    ptr_t domain_local;
+    ptr_t domain_mapped;
+};
+
+struct irq_msi_wire
+{
+    ptr_t message;
+    ptr_t sideband;
+    ptr_t wr_addr;
+};
+
+struct irq_object
+{    
+    enum irq_type type;
+    unsigned int vector;
+    
+    union {
+        struct irq_line_wire* line;
+        struct irq_msi_wire* msi;
+    };
+
+    irq_servant serve;
+    void* payload;
+
+    struct irq_domain* domain;
+    void* irq_extra;
+    int ref;
+};
+
+#define SZ sizeof(struct irq_object)
+
+struct irq_domain*
+irq_create_domain(struct device* intc_dev, const struct irq_domain_ops* ops);
+
+struct irq_domain*
+irq_owning_domain(struct device* dev);
+
+int
+irq_attach_domain(struct irq_domain* parent, struct irq_domain* child);
+
+irq_t
+irq_declare(enum irq_type, irq_servant, ptr_t, void*);
+
+void
+irq_revoke(irq_t);
+
+int
+irq_assign(struct irq_domain* domain, irq_t);
+
+irq_t
+irq_find(struct irq_domain* domain, int local_irq);
+
+void
+irq_record(struct irq_domain* domain, irq_t irq);
+
+void
+irq_set_default_domain(struct irq_domain*);
+
+struct irq_domain*
+irq_get_default_domain();
+
+int
+irq_forward_install(struct irq_domain* current, irq_t irq);
+
+static inline void
+irq_serve(irq_t irq, struct hart_state* state)
+{
+    irq->serve(irq, state);
+}
+
+static inline void
+irq_set_payload(irq_t irq, void* payload)
+{
+    irq->payload = payload;
+}
+
+static inline void
+irq_set_domain_object(struct irq_domain* domain, void* obj)
+{
+    domain->object = obj;
+}
+
+#define irq_payload(irq, type)              ((type*)(irq)->payload)
+#define irq_domain_obj(domain, type)        ((type*)(domain)->object)
+
+static inline irq_t
+irq_declare_line(irq_servant callback, int local_irq, void* irq_extra)
+{
+    return irq_declare(IRQ_LINE, callback, (int)local_irq, irq_extra);
+}
+
+static inline irq_t
+irq_declare_msg(irq_servant callback, 
+                ptr_t message, ptr_t sideband, void* irq_extra)
+{
+    irq_t irq;
+    irq = irq_declare(IRQ_MESSAGE, callback, message, irq_extra);
+    irq->msi->sideband = sideband;
+
+    return irq;
+}
+
+static inline struct irq_domain*
+irq_get_domain(struct device* maybe_intc)
+{
+    struct potens_meta* domain_m;
+
+    domain_m = device_get_potens(maybe_intc, potens(INT_DOMAIN));
+    return domain_m ? get_potens(domain_m, struct irq_domain) : NULL;
+}
+
+static inline struct irq_domain*
+irq_parent_domain(struct irq_domain* domain)
+{
+    return domain->parent;
+}
+
+#endif /* __LUNAIX_IRQ_H */
index 37815fefb8a41e71a12ce0981225dae5fc438128..8c7057a318c0a3e008ad30c18a73fba3e7311390 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <asm-generic/isrm.h>
 
+#include "irq.h"
+
 #define PCI_VENDOR_INVLD 0xffff
 
 #define PCI_REG_VENDOR_DEV 0
@@ -86,6 +88,7 @@ struct pci_probe
     struct pci_base_addr bar[6];
 
     struct device* bind;
+    struct irq_domain* irq_domain;
 };
 #define pci_probe_morpher   morphable_attrs(pci_probe, mobj)
 
@@ -115,6 +118,13 @@ pci_register_driver(struct device_def* def, pci_id_checker_t checker);
 size_t
 pci_bar_sizing(struct pci_probe* probe, u32_t* bar_out, u32_t bar_num);
 
+irq_t
+pci_declare_msi_irq(irq_servant callback, 
+                    struct pci_probe* probe, void *irq_extra);
+
+int
+pci_assign_msi(struct pci_probe* probe, irq_t irq);
+
 /**
  * @brief Bind an abstract device instance to the pci device
  *
@@ -128,32 +138,6 @@ pci_bind_instance(struct pci_probe* probe, struct device* dev)
 
 }
 
-msienv_t
-pci_msi_start(struct pci_probe* probe);
-
-msi_vector_t
-pci_msi_setup_at(msienv_t msienv, struct pci_probe* probe, 
-                 int i, isr_cb handler);
-
-static inline void
-pci_msi_done(msienv_t env)
-{
-    isrm_msi_done(env);
-}
-
-static inline msi_vector_t
-pci_msi_setup_simple(struct pci_probe* probe, isr_cb handler)
-{
-    msienv_t env;
-    msi_vector_t msiv;
-    
-    env = pci_msi_start(probe);
-    msiv = pci_msi_setup_at(env, probe, 0, handler);
-    pci_msi_done(env);
-
-    return msiv;
-}
-
 int
 pci_bind_driver(struct pci_registry* reg);
 
index aecd7d4d2446d820d0974b9098427996c7a76506..62253e91d4cab426f17fc006fb542cbd7675a3a3 100644 (file)
@@ -4,4 +4,5 @@ morphable(pci_probe),
 morphable(device_meta),
 morphable(device_cat),
 morphable(device_alias),
-morphable(device),
\ No newline at end of file
+morphable(device),
+morphable(irq_object),
\ No newline at end of file
index 9534b9a700fc7bb3dabe95d138a3c37556480c28..9b80f90a6b25b85e1ba2eaad13ad060d6368fc5b 100644 (file)
@@ -17,4 +17,10 @@ potens(HWTIMER),
  * @brief RTC capability.
  * 
  */
-potens(HWRTC),
\ No newline at end of file
+potens(HWRTC),
+
+/**
+ * @brief Interrupt controller (domain) capability
+ * 
+ */
+potens(INT_DOMAIN),
\ No newline at end of file
index f1ce4d0df9a1bbfa19f4cc14cdf28f2875b74932..7a469a113c725b31e1fba06cb0c0667788f9dcb1 100644 (file)
@@ -353,11 +353,13 @@ device_create(struct device* dev,
 struct device*
 device_alloc(struct device_meta* parent, u32_t type, void* underlay);
 
+#ifdef CONFIG_USE_DEVICETREE
 static inline void
 device_set_devtree_node(struct device* dev, devtree_link_t node)
 {
     dev->devtree_node = node;
 }
+#endif
 
 static inline struct device* must_inline
 device_allocsys(struct device_meta* parent, void* underlay)
index 31775bfdf7c36d19c77120c3a67d76da2e11d747..a154b0d1a0127d9dc0f4e158f7a51561c9f618c8 100644 (file)
@@ -221,7 +221,6 @@ schedule()
     sched_ctx.procs_index = to_check->process->pid;
 
 done:
-    isrm_notify_eos(0);
     run(to_check);
 
     fail("unexpected return from scheduler");