From: Lunaixsky Date: Sun, 8 Dec 2024 15:41:35 +0000 (+0000) Subject: rework external irq system, introduce hierarchical irq X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/836d44ecb7a2c37427f6baf8b25e872e9e943d5b rework external irq system, introduce hierarchical irq --- diff --git a/lunaix-os/arch/generic/includes/asm-generic/isrm.h b/lunaix-os/arch/generic/includes/asm-generic/isrm.h index 0d4a15a..5f82aca 100644 --- a/lunaix-os/arch/generic/includes/asm-generic/isrm.h +++ b/lunaix-os/arch/generic/includes/asm-generic/isrm.h @@ -19,98 +19,9 @@ 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 */ diff --git a/lunaix-os/arch/x86/exceptions/intr_routines.c b/lunaix-os/arch/x86/exceptions/intr_routines.c index 5e18496..9410f76 100644 --- a/lunaix-os/arch/x86/exceptions/intr_routines.c +++ b/lunaix-os/arch/x86/exceptions/intr_routines.c @@ -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(); } diff --git a/lunaix-os/arch/x86/exceptions/isrm.c b/lunaix-os/arch/x86/exceptions/isrm.c index 86eec04..cd2d81b 100644 --- a/lunaix-os/arch/x86/exceptions/isrm.c +++ b/lunaix-os/arch/x86/exceptions/isrm.c @@ -1,9 +1,7 @@ #include -#include #include #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 diff --git a/lunaix-os/arch/x86/hal/LBuild b/lunaix-os/arch/x86/hal/LBuild index f3a3cae..870f743 100644 --- a/lunaix-os/arch/x86/hal/LBuild +++ b/lunaix-os/arch/x86/hal/LBuild @@ -4,7 +4,6 @@ sources([ "cpu.c", "ps2kbd.c", "apic_timer.c", - "ioapic.c", "mc146818a.c", "pci.c" ]) \ No newline at end of file diff --git a/lunaix-os/arch/x86/hal/apic.c b/lunaix-os/arch/x86/hal/apic.c index ddc2e31..cd03096 100644 --- a/lunaix-os/arch/x86/hal/apic.c +++ b/lunaix-os/arch/x86/hal/apic.c @@ -11,24 +11,90 @@ #include "asm/x86.h" #include "asm/x86_cpu.h" - #include "asm/soc/apic.h" + #include +#include #include #include #include +#include + +#include +#include #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 index e03d4b5..0000000 --- a/lunaix-os/arch/x86/hal/ioapic.c +++ /dev/null @@ -1,89 +0,0 @@ -#include - -#include - -#include -#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 diff --git a/lunaix-os/arch/x86/hal/mc146818a.c b/lunaix-os/arch/x86/hal/mc146818a.c index f5bc285..ec2cd4b 100644 --- a/lunaix-os/arch/x86/hal/mc146818a.c +++ b/lunaix-os/arch/x86/hal/mc146818a.c @@ -15,6 +15,7 @@ #include #include +#include #include @@ -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; } diff --git a/lunaix-os/arch/x86/hal/ps2kbd.c b/lunaix-os/arch/x86/hal/ps2kbd.c index ee4a67e..8799da2 100644 --- a/lunaix-os/arch/x86/hal/ps2kbd.c +++ b/lunaix-os/arch/x86/hal/ps2kbd.c @@ -6,6 +6,8 @@ #include #include +#include + #include "asm/x86.h" #include @@ -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! diff --git a/lunaix-os/arch/x86/includes/asm/soc/apic.h b/lunaix-os/arch/x86/includes/asm/soc/apic.h index 40c395c..83ad3ed 100644 --- a/lunaix-os/arch/x86/includes/asm/soc/apic.h +++ b/lunaix-os/arch/x86/includes/asm/soc/apic.h @@ -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 index d87ab18..0000000 --- a/lunaix-os/arch/x86/includes/asm/soc/ioapic.h +++ /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 */ diff --git a/lunaix-os/arch/x86/includes/asm/x86_isrm.h b/lunaix-os/arch/x86/includes/asm/x86_isrm.h index b486080..4d6fb44 100644 --- a/lunaix-os/arch/x86/includes/asm/x86_isrm.h +++ b/lunaix-os/arch/x86/includes/asm/x86_isrm.h @@ -3,14 +3,6 @@ #include -/** - * @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 */ diff --git a/lunaix-os/hal/LBuild b/lunaix-os/hal/LBuild index 673a8fc..6ff2713 100644 --- a/lunaix-os/hal/LBuild +++ b/lunaix-os/hal/LBuild @@ -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 diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 04a7104..7d0b9b2 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -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); diff --git a/lunaix-os/hal/ahci/ahci_pci.c b/lunaix-os/hal/ahci/ahci_pci.c index 4435da1..6c4fdde 100644 --- a/lunaix-os/hal/ahci/ahci_pci.c +++ b/lunaix-os/hal/ahci/ahci_pci.c @@ -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(¶m); diff --git a/lunaix-os/hal/ahci/io_event.c b/lunaix-os/hal/ahci/io_event.c index 608634d..c40a85c 100644 --- a/lunaix-os/hal/ahci/io_event.c +++ b/lunaix-os/hal/ahci/io_event.c @@ -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)) { diff --git a/lunaix-os/hal/bus/pci.c b/lunaix-os/hal/bus/pci.c index 3052a90..3e940e0 100644 --- a/lunaix-os/hal/bus/pci.c +++ b/lunaix-os/hal/bus/pci.c @@ -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); diff --git a/lunaix-os/hal/char/uart/16x50.h b/lunaix-os/hal/char/uart/16x50.h index 40ebe94..4a2c8a5 100644 --- a/lunaix-os/hal/char/uart/16x50.h +++ b/lunaix-os/hal/char/uart/16x50.h @@ -2,6 +2,7 @@ #define __LUNAIX_16550_H #include +#include #include #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, diff --git a/lunaix-os/hal/char/uart/16x50_base.c b/lunaix-os/hal/char/uart/16x50_base.c index 8b3930f..5b14445 100644 --- a/lunaix-os/hal/char/uart/16x50_base.c +++ b/lunaix-os/hal/char/uart/16x50_base.c @@ -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; diff --git a/lunaix-os/hal/char/uart/16x50_isa.c b/lunaix-os/hal/char/uart/16x50_isa.c index 3958223..c24c1d0 100644 --- a/lunaix-os/hal/char/uart/16x50_isa.c +++ b/lunaix-os/hal/char/uart/16x50_isa.c @@ -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; diff --git a/lunaix-os/hal/char/uart/16x50_pci.c b/lunaix-os/hal/char/uart/16x50_pci.c index 20beda1..9de2396 100644 --- a/lunaix-os/hal/char/uart/16x50_pci.c +++ b/lunaix-os/hal/char/uart/16x50_pci.c @@ -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 index 0000000..b4bc0ec --- /dev/null +++ b/lunaix-os/hal/irq.c @@ -0,0 +1,195 @@ +#include +#include +#include + +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(¤t->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; +} diff --git a/lunaix-os/includes/hal/ahci/ahci.h b/lunaix-os/includes/hal/ahci/ahci.h index 7eaf10d..b55ba95 100644 --- a/lunaix-os/includes/hal/ahci/ahci.h +++ b/lunaix-os/includes/hal/ahci/ahci.h @@ -3,6 +3,7 @@ #include "hba.h" #include +#include /* * 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 */ diff --git a/lunaix-os/includes/hal/devtree.h b/lunaix-os/includes/hal/devtree.h index e7e0cf3..ae18e31 100644 --- a/lunaix-os/includes/hal/devtree.h +++ b/lunaix-os/includes/hal/devtree.h @@ -1,6 +1,7 @@ #ifndef __LUNAIX_DEVTREE_H #define __LUNAIX_DEVTREE_H +#ifdef CONFIG_USE_DEVICETREE #include #include #include @@ -727,4 +728,5 @@ dtpi_next_val(struct dtpropi* dtpi, struct dtp_val* val, int cells) return true; } +#endif #endif /* __LUNAIX_DEVTREE_H */ diff --git a/lunaix-os/includes/hal/devtreem.h b/lunaix-os/includes/hal/devtreem.h index 2b0904d..d235cd7 100644 --- a/lunaix-os/includes/hal/devtreem.h +++ b/lunaix-os/includes/hal/devtreem.h @@ -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 index 0000000..e592e22 --- /dev/null +++ b/lunaix-os/includes/hal/irq.h @@ -0,0 +1,162 @@ +#ifndef __LUNAIX_IRQ_H +#define __LUNAIX_IRQ_H + +#include +#include +#include +#include + +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 */ diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h index 37815fe..8c7057a 100644 --- a/lunaix-os/includes/hal/pci.h +++ b/lunaix-os/includes/hal/pci.h @@ -10,6 +10,8 @@ #include +#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); diff --git a/lunaix-os/includes/listings/changeling.lst b/lunaix-os/includes/listings/changeling.lst index aecd7d4..62253e9 100644 --- a/lunaix-os/includes/listings/changeling.lst +++ b/lunaix-os/includes/listings/changeling.lst @@ -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 diff --git a/lunaix-os/includes/listings/device_potens.lst b/lunaix-os/includes/listings/device_potens.lst index 9534b9a..9b80f90 100644 --- a/lunaix-os/includes/listings/device_potens.lst +++ b/lunaix-os/includes/listings/device_potens.lst @@ -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 diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index f1ce4d0..7a469a1 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -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) diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 31775bf..a154b0d 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -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");