From 35a7d633d3f16c1e0539af6ca5d8e7482926cd93 Mon Sep 17 00:00:00 2001 From: Lunaixsky Date: Wed, 20 Nov 2024 00:49:12 +0000 Subject: [PATCH 1/1] rewrite the device subsystem interfaces (#48) * add a new initfn stage for decoupling, adjust loading orders * promote x86 intc to proper device rather than init fn * add devtree compatible driver manager * fix some issues in the devtree implementation * rewrite pci device model for peripherals * introduce changeling, or morphable. with main purpose of managing and decouple the objects that are passing around within the kernel, especially in device subsystem, things getting even more chaos. * rewrite the pci device model such that it: 1. provides unified way to export device driver, we completely remove the use of EXPORT_PCI_DEVICE 2. better integration with devicetree assisted device initialisation and configuration. 3. give the entire freedom to driver decide how to spawn their struct device instance. * re-organise the deivce_def to make the hooks more general and universal. * refactor device_def and device numbering * refactor the declaration of device_def more intuitive, enhance readbility * rename the device capability into potens * refactor the device numbering, using enum, remove the need of manually maintain the number. New macros allow developer to focus only on the name rather than prefixes/conventions. * minor fixes. * refactor the hwtimer/hwrtc with potens. * load and init of hwtimer and hwrtc are now done through the potens. * streamline the term dev creation by unifying with the potens. * move the *.lst file to a dedicated directory * minor cleanups * glue the device objects into devfs using changelings. * minor code cleanup * cleanup: remove the lx_timer_context * use safer method to resolve inode embedded device morpher * rework the dtm and allow pattern based compat field matching * add implementation for fast strlen and strnlen for x86 * use weak alias to decouple realm-specific impl. of hooks * replace device interface with device vendor in devclass * rename the weak to _weak for avoid accidential expansion * enable small function inlining as default optimization * move isrm_ivosalloc and isrm_ivexalloc to x86 specific * add comment regarding the regular expr used by pattern matcher --- lunaix-os/arch/generic/arch.c | 6 - .../arch/generic/includes/asm-generic/isrm.h | 50 +- lunaix-os/arch/x86/arch.c | 15 - lunaix-os/arch/x86/exceptions/isrm.c | 56 +- lunaix-os/arch/x86/hal/apic_timer.c | 131 ++--- lunaix-os/arch/x86/hal/mc146818a.c | 116 ++-- lunaix-os/arch/x86/hal/ps2kbd.c | 8 +- lunaix-os/arch/x86/hal/rngx86.c | 9 +- lunaix-os/arch/x86/includes/asm/x86_isrm.h | 15 + lunaix-os/arch/x86/klib/fast_str.c | 31 ++ lunaix-os/hal/LBuild | 2 +- lunaix-os/hal/acpi/acpi.c | 10 +- lunaix-os/hal/ahci/ahci.c | 2 +- lunaix-os/hal/ahci/ahci_pci.c | 58 +- lunaix-os/hal/bus/pci.c | 511 ++++++++++-------- lunaix-os/hal/char/devnull.c | 9 +- lunaix-os/hal/char/devzero.c | 9 +- lunaix-os/hal/char/lxconsole.c | 22 +- lunaix-os/hal/char/serial.c | 30 +- lunaix-os/hal/char/uart/16x50_dev.c | 44 ++ lunaix-os/hal/char/uart/16x50_isa.c | 13 +- lunaix-os/hal/char/uart/16x50_pci.c | 55 +- lunaix-os/hal/char/uart/LBuild | 1 + lunaix-os/hal/devtree/LBuild | 5 + lunaix-os/hal/devtree/devtree.h | 38 ++ lunaix-os/hal/devtree/dt.c | 130 ++--- lunaix-os/hal/devtree/dt_interrupt.c | 6 +- lunaix-os/hal/devtree/dtm.c | 219 ++++++++ lunaix-os/hal/gfxa/gfxm.c | 2 +- lunaix-os/hal/gfxa/vga/vga_pci.c | 48 +- lunaix-os/hal/rtc/rtc_device.c | 141 +++-- lunaix-os/hal/term/console.c | 2 +- lunaix-os/hal/term/default_ops.c | 2 +- lunaix-os/hal/term/term.c | 45 +- lunaix-os/hal/term/term_io.c | 2 +- lunaix-os/hal/timer/timer_device.c | 81 ++- lunaix-os/includes/hal/devtree.h | 50 +- lunaix-os/includes/hal/devtreem.h | 48 ++ lunaix-os/includes/hal/hwrtc.h | 39 +- lunaix-os/includes/hal/hwtimer.h | 38 +- lunaix-os/includes/hal/pci.h | 146 +++-- lunaix-os/includes/hal/serial.h | 3 +- lunaix-os/includes/hal/term.h | 45 +- lunaix-os/includes/listings/changeling.lst | 7 + lunaix-os/includes/listings/device_potens.lst | 20 + lunaix-os/includes/listings/devnum.lst | 20 + lunaix-os/includes/listings/devnum_fn.lst | 9 + lunaix-os/includes/listings/devnum_vn.lst | 3 + lunaix-os/includes/lunaix/changeling.h | 171 ++++++ lunaix-os/includes/lunaix/clock.h | 13 +- lunaix-os/includes/lunaix/compiler.h | 4 +- lunaix-os/includes/lunaix/device.h | 345 ++++++++---- lunaix-os/includes/lunaix/device_num.h | 75 +-- lunaix-os/includes/lunaix/ds/list.h | 67 +++ lunaix-os/includes/lunaix/owloysius.h | 30 + lunaix-os/includes/lunaix/sections.h | 2 +- lunaix-os/includes/lunaix/timer.h | 29 - lunaix-os/kernel/LBuild | 1 + lunaix-os/kernel/block/blkbuf.c | 2 +- lunaix-os/kernel/changeling.c | 79 +++ lunaix-os/kernel/device/LBuild | 4 +- lunaix-os/kernel/device/capability.c | 32 -- lunaix-os/kernel/device/devdb.c | 28 +- lunaix-os/kernel/device/devfs.c | 73 ++- lunaix-os/kernel/device/device.c | 236 ++++---- lunaix-os/kernel/device/potentem.c | 33 ++ lunaix-os/kernel/fs/mount.c | 9 +- lunaix-os/kernel/fs/vfs.c | 6 +- lunaix-os/kernel/kinit.c | 15 +- lunaix-os/kernel/time/clock.c | 25 +- lunaix-os/kernel/time/timer.c | 22 +- lunaix-os/libs/crc.c | 2 +- lunaix-os/libs/hash.c | 2 +- lunaix-os/libs/klibc/string/mem.c | 8 +- lunaix-os/libs/klibc/string/strchr.c | 2 +- lunaix-os/libs/klibc/string/strcmp.c | 2 +- lunaix-os/libs/klibc/string/strcpy.c | 4 +- lunaix-os/libs/klibc/string/strlen.c | 4 +- lunaix-os/libs/klibc/string/trim.c | 4 +- lunaix-os/link/lga.ldx | 18 +- lunaix-os/live_debug.sh | 2 +- lunaix-os/makefile | 1 - lunaix-os/makeinc/toolchain.mkinc | 3 +- 83 files changed, 2347 insertions(+), 1358 deletions(-) create mode 100644 lunaix-os/hal/char/uart/16x50_dev.c create mode 100644 lunaix-os/hal/devtree/LBuild create mode 100644 lunaix-os/hal/devtree/dtm.c create mode 100644 lunaix-os/includes/hal/devtreem.h create mode 100644 lunaix-os/includes/listings/changeling.lst create mode 100644 lunaix-os/includes/listings/device_potens.lst create mode 100644 lunaix-os/includes/listings/devnum.lst create mode 100644 lunaix-os/includes/listings/devnum_fn.lst create mode 100644 lunaix-os/includes/listings/devnum_vn.lst create mode 100644 lunaix-os/includes/lunaix/changeling.h create mode 100644 lunaix-os/includes/lunaix/ds/list.h create mode 100644 lunaix-os/kernel/changeling.c delete mode 100644 lunaix-os/kernel/device/capability.c create mode 100644 lunaix-os/kernel/device/potentem.c mode change 100755 => 100644 lunaix-os/libs/klibc/string/mem.c diff --git a/lunaix-os/arch/generic/arch.c b/lunaix-os/arch/generic/arch.c index 3e62e7b..609d641 100644 --- a/lunaix-os/arch/generic/arch.c +++ b/lunaix-os/arch/generic/arch.c @@ -1,8 +1,2 @@ #include #include - -_default struct hwtimer* -select_platform_timer() -{ - fail("not implemented"); -} \ No newline at end of file diff --git a/lunaix-os/arch/generic/includes/asm-generic/isrm.h b/lunaix-os/arch/generic/includes/asm-generic/isrm.h index e8117bb..0bd4dda 100644 --- a/lunaix-os/arch/generic/includes/asm-generic/isrm.h +++ b/lunaix-os/arch/generic/includes/asm-generic/isrm.h @@ -13,6 +13,7 @@ #include #include +#include #include @@ -27,6 +28,8 @@ typedef struct { #define msi_data(msiv) ((msiv).msi_data) #define msi_vect(msiv) ((msiv).mapped_iv) +typedef void* msienv_t; + void isrm_init(); @@ -39,28 +42,51 @@ void isrm_ivfree(int iv); /** - * @brief Allocate an iv resource for os services + * @brief Begin MSI allocation for given device * * @param iv */ -int -isrm_ivosalloc(isr_cb handler); +msienv_t +isrm_msi_start(struct device* dev); /** - * @brief Allocate an iv resource for external events - * - * @param iv + * @brief Query number of msi avaliable for the device */ int -isrm_ivexalloc(isr_cb handler); +isrm_msi_avaliable(msienv_t msienv); /** - * @brief Allocate an iv resource for MSI use - * - * @param iv + * @brief Allocate a msi resource within defined msi resource list + * for the device, indexed by `index` */ msi_vector_t -isrm_msialloc(isr_cb handler); +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 @@ -68,7 +94,7 @@ isrm_msialloc(isr_cb handler); * @param node */ int -isrm_bind_dtnode(struct dt_intr_node* node); +isrm_bind_dtn(struct dt_intr_node* node); /** * @brief Get the handler associated with the given iv diff --git a/lunaix-os/arch/x86/arch.c b/lunaix-os/arch/x86/arch.c index f29b598..e98bdd9 100644 --- a/lunaix-os/arch/x86/arch.c +++ b/lunaix-os/arch/x86/arch.c @@ -29,21 +29,6 @@ arch_preinit() isrm_bindiv(LUNAIX_SYS_CALL, syscall_hndlr); } -struct hwtimer* -select_platform_timer() -{ - struct hwtimer* timer; - - timer = apic_hwtimer_context(); - if (timer->supported(timer)) { - return timer; - } - - // TODO select alternatives... - - fail("no timer to use."); -} - void update_tss() { diff --git a/lunaix-os/arch/x86/exceptions/isrm.c b/lunaix-os/arch/x86/exceptions/isrm.c index a3c223d..fefc33e 100644 --- a/lunaix-os/arch/x86/exceptions/isrm.c +++ b/lunaix-os/arch/x86/exceptions/isrm.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include "asm/x86.h" @@ -165,27 +165,60 @@ 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_msialloc(isr_cb handler) +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 = 0xfee00000, + .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_dtnode(struct dt_intr_node* node) +isrm_bind_dtn(struct dt_intr_node* node) { fail("not supported"); } -static void -__intc_init() +static int +__intc_create(struct device_def* devdef, morph_t* obj) { apic_init(); ioapic_init(); @@ -193,5 +226,14 @@ __intc_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; } -owloysius_fetch_init(__intc_init, on_earlyboot); \ No newline at end of file + + +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 diff --git a/lunaix-os/arch/x86/hal/apic_timer.c b/lunaix-os/arch/x86/hal/apic_timer.c index 56cd410..816fde3 100644 --- a/lunaix-os/arch/x86/hal/apic_timer.c +++ b/lunaix-os/arch/x86/hal/apic_timer.c @@ -9,72 +9,45 @@ #include #include "asm/soc/apic.h" -LOG_MODULE("APIC_TIMER") +LOG_MODULE("timer(apic)") #define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector) #define APIC_BASETICKS 0x100000 -// Don't optimize them! Took me an half hour to figure that out... - -static volatile u8_t apic_timer_done = 0; -static volatile ticks_t base_freq = 0; -static volatile ticks_t systicks = 0; - -static timer_tick_cb tick_cb = NULL; - static void temp_intr_routine_apic_timer(const struct hart_state* state) { - apic_timer_done = 1; + struct hwtimer_pot* pot; + + pot = (struct hwtimer_pot*)isrm_get_payload(state); + pot->systick_raw = (ticks_t)-1; } static void apic_timer_tick_isr(const struct hart_state* state) { - systicks++; - - if (likely((ptr_t)tick_cb)) { - tick_cb(); - } -} - -static int -apic_timer_check(struct hwtimer* hwt) -{ - // TODO check whether apic timer is supported - return 1; -} + struct hwtimer_pot* pot; -static ticks_t -apic_get_systicks() -{ - return systicks; -} + pot = (struct hwtimer_pot*)isrm_get_payload(state); + pot->systick_raw++; -static ticks_t -apic_get_base_freq() -{ - return base_freq; + if (likely(__ptr(pot->callback))) { + pot->callback(); + } } -void -apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb) +static void +__apic_timer_calibrate(struct hwtimer_pot* pot, u32_t hertz) { - ticks_t frequency = hertz; - tick_cb = timer_cb; + ticks_t base_freq = 0; cpu_disable_interrupt(); // Setup APIC timer - // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic - // (Remarks IRQ 8 is pin INTIN8) - // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ - // See Intel's Multiprocessor Specification for IRQ - IOAPIC INTIN - // mapping config. - // grab ourselves these irq numbers u32_t iv_timer = isrm_ivexalloc(temp_intr_routine_apic_timer); + isrm_set_payload(iv_timer, __ptr(pot)); // Setup a one-shot timer, we will use this to measure the bus speed. So we // can then calibrate apic timer to work at *nearly* accurate hz @@ -107,55 +80,59 @@ apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb) */ -#ifdef __LUNAIXOS_DEBUG__ - if (frequency < 1000) { - WARN("Frequency too low. Millisecond timer might be dodgy."); - } -#endif - - apic_timer_done = 0; - - sysrtc->cls_mask(sysrtc); + sysrtc->ops->set_proactive(sysrtc, true); apic_write_reg(APIC_TIMER_ICR, APIC_BASETICKS); // start APIC timer - // enable interrupt, just for our RTC start ticking! + pot->systick_raw = 0; cpu_enable_interrupt(); - wait_until(apic_timer_done); + wait_until(!(pot->systick_raw + 1)); cpu_disable_interrupt(); + isrm_ivfree(iv_timer); - sysrtc->set_mask(sysrtc); - - base_freq = sysrtc->get_counts(sysrtc); + sysrtc->ops->set_proactive(sysrtc, false); + + base_freq = sysrtc->live; base_freq = APIC_BASETICKS / base_freq * sysrtc->base_freq; + pot->base_freq = base_freq; + pot->systick_raw = 0; assert_msg(base_freq, "Fail to initialize timer (NOFREQ)"); + INFO("hw: %u Hz; os: %u Hz", base_freq, hertz); - kprintf("hw: %u Hz; os: %u Hz", base_freq, frequency); + apic_write_reg(APIC_TIMER_ICR, base_freq / hertz); + + iv_timer = isrm_ivexalloc(apic_timer_tick_isr); + isrm_set_payload(iv_timer, __ptr(pot)); + + apic_write_reg( + APIC_TIMER_LVT, + LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_PERIODIC)); +} - // cleanup - isrm_ivfree(iv_timer); +static struct hwtimer_pot_ops potops = { + .calibrate = __apic_timer_calibrate, +}; - ticks_t tphz = base_freq / frequency; - timer->base_freq = base_freq; - apic_write_reg(APIC_TIMER_ICR, tphz); +static int +__apic_timer_load(struct device_def* def) +{ + struct device* timer; - apic_write_reg( - APIC_TIMER_LVT, - LVT_ENTRY_TIMER(isrm_ivexalloc(apic_timer_tick_isr), LVT_TIMER_PERIODIC)); + timer = device_allocsys(NULL, NULL); + + hwtimer_attach_potens(timer, HWTIMER_MAX_PRECEDENCE, &potops); + register_device_var(timer, &def->class, "apic-timer"); + return 0; } -struct hwtimer* -apic_hwtimer_context() + +static struct device_def x86_apic_timer = { - static struct hwtimer apic_hwt = { - .name = "apic_timer", - .class = DEVCLASSV(DEVIF_SOC, DEVFN_TIME, DEV_TIMER, DEV_TIMER_APIC), - .init = apic_timer_init, - .supported = apic_timer_check, - .systicks = apic_get_systicks - }; - - return &apic_hwt; -} + def_device_class(INTEL, TIME, TIMER_APIC), + def_device_name("Intel APIC Timer"), + + def_on_load(__apic_timer_load) +}; +EXPORT_DEVICE(apic_timer, &x86_apic_timer, load_sysconf); diff --git a/lunaix-os/arch/x86/hal/mc146818a.c b/lunaix-os/arch/x86/hal/mc146818a.c index 9c788f9..f5bc285 100644 --- a/lunaix-os/arch/x86/hal/mc146818a.c +++ b/lunaix-os/arch/x86/hal/mc146818a.c @@ -24,8 +24,6 @@ #define RTC_INDEX_PORT 0x70 #define RTC_TARGET_PORT 0x71 -#define WITH_NMI_DISABLED 0x80 - #define RTC_CURRENT_CENTRY 20 #define RTC_REG_YRS 0x9 @@ -58,35 +56,34 @@ struct mc146818 { - struct hwrtc* rtc_context; + struct hwrtc_potens* rtc_context; u32_t rtc_iv; - u32_t tick_counts; }; #define rtc_state(data) ((struct mc146818*)(data)) -static u8_t +static inline u8_t rtc_read_reg(u8_t reg_selector) { port_wrbyte(RTC_INDEX_PORT, reg_selector); return port_rdbyte(RTC_TARGET_PORT); } -static void +static inline void rtc_write_reg(u8_t reg_selector, u8_t val) { port_wrbyte(RTC_INDEX_PORT, reg_selector); port_wrbyte(RTC_TARGET_PORT, val); } -static void +static inline void rtc_enable_timer() { u8_t regB = rtc_read_reg(RTC_REG_B); rtc_write_reg(RTC_REG_B, regB | RTC_TIMER_ON); } -static void +static inline void rtc_disable_timer() { u8_t regB = rtc_read_reg(RTC_REG_B); @@ -94,7 +91,7 @@ rtc_disable_timer() } static void -rtc_getwalltime(struct hwrtc* rtc, datetime_t* datetime) +rtc_getwalltime(struct hwrtc_potens* rtc, datetime_t* datetime) { datetime_t current; @@ -116,7 +113,7 @@ rtc_getwalltime(struct hwrtc* rtc, datetime_t* datetime) } static void -rtc_setwalltime(struct hwrtc* rtc, datetime_t* datetime) +rtc_setwalltime(struct hwrtc_potens* rtc, datetime_t* datetime) { u8_t reg = rtc_read_reg(RTC_REG_B); reg = reg & ~RTC_SET; @@ -134,59 +131,40 @@ rtc_setwalltime(struct hwrtc* rtc, datetime_t* datetime) rtc_write_reg(RTC_REG_B, reg & ~RTC_SET); } -static int -mc146818_check_support(struct hwrtc* rtc) -{ -#if __ARCH__ == i386 - return 1; -#else - return 0; -#endif -} - static void __rtc_tick(const struct hart_state* hstate) { struct mc146818* state = (struct mc146818*)isrm_get_payload(hstate); - state->tick_counts++; + state->rtc_context->live++; (void)rtc_read_reg(RTC_REG_C); } static void -rtc_set_mask(struct hwrtc* rtc) +rtc_set_proactive(struct hwrtc_potens* pot, bool proactive) { - rtc->state = RTC_STATE_MASKED; - rtc_disable_timer(); -} - -static void -rtc_cls_mask(struct hwrtc* rtc) -{ - struct mc146818* state = rtc_state(rtc->data); - - rtc->state = 0; - state->tick_counts = 0; - rtc_enable_timer(); + if (proactive) { + pot->state = 0; + rtc_enable_timer(); + } + else { + pot->state = RTC_STATE_MASKED; + rtc_disable_timer(); + } } static int -rtc_chfreq(struct hwrtc* rtc, int freq) +rtc_chfreq(struct hwrtc_potens* rtc, int freq) { return ENOTSUP; } static int -rtc_getcnt(struct hwrtc* rtc) +__rtc_calibrate(struct hwrtc_potens* pot) { - struct mc146818* state = rtc_state(rtc->data); - return state->tick_counts; -} + struct mc146818* state; -static int -rtc_init(struct device_def* devdef) -{ u8_t reg = rtc_read_reg(RTC_REG_A); reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; rtc_write_reg(RTC_REG_A, reg); @@ -197,31 +175,49 @@ rtc_init(struct device_def* devdef) // Make sure the rtc timer is disabled by default rtc_disable_timer(); - struct hwrtc* rtc = hwrtc_alloc_new("mc146818"); - struct mc146818* state = valloc(sizeof(struct mc146818)); + pot->base_freq = RTC_TIMER_BASE_FREQUENCY; - state->rtc_context = rtc; + 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_t)state); + isrm_set_payload(state->rtc_iv, __ptr(state)); + + return 0; +} + +static struct hwrtc_potens_ops ops = { + .get_walltime = rtc_getwalltime, + .set_walltime = rtc_setwalltime, + .set_proactive = rtc_set_proactive, + .chfreq = rtc_chfreq, + .calibrate = __rtc_calibrate +}; + +static int +rtc_load(struct device_def* devdef) +{ + struct device* dev; + struct mc146818* state; + struct hwrtc_potens* pot; + + state = valloc(sizeof(struct mc146818)); + dev = device_allocsys(NULL, state); + + pot = hwrtc_attach_potens(dev, &ops); + if (!pot) { + return 1; + } - rtc->state = RTC_STATE_MASKED; - rtc->data = state; - rtc->base_freq = RTC_TIMER_BASE_FREQUENCY; - rtc->get_walltime = rtc_getwalltime; - rtc->set_walltime = rtc_setwalltime; - rtc->set_mask = rtc_set_mask; - rtc->cls_mask = rtc_cls_mask; - rtc->get_counts = rtc_getcnt; - rtc->chfreq = rtc_chfreq; + pot->state = RTC_STATE_MASKED; + state->rtc_context = pot; - hwrtc_register(&devdef->class, rtc); + register_device(dev, &devdef->class, "mc146818"); return 0; } static struct device_def devrtc_mc146818 = { - .name = "MC146818 RTC", - .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC), - .init = rtc_init + def_device_class(INTEL, TIME, RTC), + def_device_name("x86 legacy RTC"), + def_on_load(rtc_load) }; -EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_timedev); \ No newline at end of file +EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_sysconf); \ No newline at end of file diff --git a/lunaix-os/arch/x86/hal/ps2kbd.c b/lunaix-os/arch/x86/hal/ps2kbd.c index 02e98d1..ee4a67e 100644 --- a/lunaix-os/arch/x86/hal/ps2kbd.c +++ b/lunaix-os/arch/x86/hal/ps2kbd.c @@ -215,7 +215,7 @@ ps2_device_post_cmd(char cmd, char arg) } static int -ps2_kbd_init(struct device_def* devdef) +ps2_kbd_create(struct device_def* devdef, morph_t* obj) { memset(&cmd_q, 0, sizeof(cmd_q)); @@ -569,8 +569,8 @@ ps2_issue_dev_cmd(char cmd, u16_t arg) } static struct device_def devrtc_i8042kbd = { - .name = "i8042 Keyboard", - .class = DEVCLASS(DEVIF_SOC, DEVFN_INPUT, DEV_KBD), - .init = ps2_kbd_init + def_device_class(INTEL, INPUT, KBD), + def_device_name("i8042 Keyboard"), + def_on_create(ps2_kbd_create) }; EXPORT_DEVICE(i8042_kbd, &devrtc_i8042kbd, load_onboot); diff --git a/lunaix-os/arch/x86/hal/rngx86.c b/lunaix-os/arch/x86/hal/rngx86.c index c444196..2baf96c 100644 --- a/lunaix-os/arch/x86/hal/rngx86.c +++ b/lunaix-os/arch/x86/hal/rngx86.c @@ -56,7 +56,7 @@ __rand_rd(struct device* dev, void* buf, size_t offset, size_t len) } int -pdev_randdev_init(struct device_def* devdef) +pdev_randdev_create(struct device_def* devdef, morph_t* obj) { // FIXME add check on cpuid for presence of rdrand struct device* devrand = device_allocseq(NULL, NULL); @@ -69,7 +69,8 @@ pdev_randdev_init(struct device_def* devdef) } static struct device_def devrandx86_def = { - .name = "x86 On-Chip RNG", - .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_RNG), - .init = pdev_randdev_init}; + def_device_class(INTEL, CHAR, RNG), + def_device_name("x86 On-Chip RNG"), + def_on_create(pdev_randdev_create) +}; EXPORT_DEVICE(randdev, &devrandx86_def, load_onboot); \ No newline at end of file diff --git a/lunaix-os/arch/x86/includes/asm/x86_isrm.h b/lunaix-os/arch/x86/includes/asm/x86_isrm.h index a2bcacd..b486080 100644 --- a/lunaix-os/arch/x86/includes/asm/x86_isrm.h +++ b/lunaix-os/arch/x86/includes/asm/x86_isrm.h @@ -23,5 +23,20 @@ isrm_bindiv(int iv, isr_cb handler); void isrm_irq_attach(int irq, int iv, cpu_t dest, u32_t flags); +/** + * @brief Allocate an iv resource for os services + * + * @param iv + */ +int +isrm_ivosalloc(isr_cb handler); + +/** + * @brief Allocate an iv resource for external events + * + * @param iv + */ +int +isrm_ivexalloc(isr_cb handler); #endif /* __LUNAIX_X86_ISRM_H */ diff --git a/lunaix-os/arch/x86/klib/fast_str.c b/lunaix-os/arch/x86/klib/fast_str.c index 2704178..d11ca1d 100644 --- a/lunaix-os/arch/x86/klib/fast_str.c +++ b/lunaix-os/arch/x86/klib/fast_str.c @@ -26,6 +26,37 @@ memset(void* ptr, int value, unsigned long num) return ptr; } +unsigned long +strlen(const char* str) +{ + unsigned long _c; + asm volatile("movq %1, %%rdi\n" + "movq $-1, %%rcx\n" + "repne scasb\n" + "neg %%rcx\n" + "movq %%rcx, %0\n" + : "=r" (_c) + : "r"(str), "a"(0) + : "rdi", "rcx", "memory"); + + return _c - 2; +} + +unsigned long +strnlen(const char* str, unsigned long max_len) +{ + unsigned long _c; + asm volatile("movq %1, %%rdi\n" + "movq %2, %%rcx\n" + "repne scasb\n" + "movq %%rcx, %0\n" + : "=r" (_c) + : "r"(str), "r"(max_len), "a"(0) + : "rdi", "rcx", "memory"); + + return max_len - _c - 1; +} + #else void* memcpy(void* dest, const void* src, unsigned long num) diff --git a/lunaix-os/hal/LBuild b/lunaix-os/hal/LBuild index f4ae4c9..673a8fc 100644 --- a/lunaix-os/hal/LBuild +++ b/lunaix-os/hal/LBuild @@ -8,4 +8,4 @@ use("timer") use("bus") if config("use_devicetree"): - sources("devtree.c") \ No newline at end of file + use("devtree") \ No newline at end of file diff --git a/lunaix-os/hal/acpi/acpi.c b/lunaix-os/hal/acpi/acpi.c index bc90ba1..b4faf63 100644 --- a/lunaix-os/hal/acpi/acpi.c +++ b/lunaix-os/hal/acpi/acpi.c @@ -1,6 +1,6 @@ #include -#include +#include #include #include #include @@ -68,7 +68,7 @@ acpi_locate_rsdp() } static int -acpi_init(struct device_def* devdef) +__gather_acpi_table() { acpi_rsdp_t* rsdp = acpi_locate_rsdp(); @@ -105,8 +105,4 @@ acpi_init(struct device_def* devdef) return 0; } -struct device_def acpi_sysdev = { .name = "ACPI Proxy", - .class = - DEVCLASS(DEVIF_FMW, DEVFN_CFG, DEV_ACPI), - .init = acpi_init }; -EXPORT_DEVICE(acpi, &acpi_sysdev, load_sysconf); \ No newline at end of file +owloysius_fetch_init(__gather_acpi_table, on_sysconf); \ No newline at end of file diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index f40ae24..04a7104 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -29,7 +29,7 @@ #define HBA_CLB_SIZE 1024 #define HBA_MY_IE (HBA_PxINTR_DHR | HBA_PxINTR_TFE | HBA_PxINTR_OF) -#define AHCI_DEVCLASS DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA) +#define AHCI_DEVCLASS DEVCLASS(LUNAIX, STORAGE, SATA) // #define DO_HBA_FULL_RESET diff --git a/lunaix-os/hal/ahci/ahci_pci.c b/lunaix-os/hal/ahci/ahci_pci.c index 7c9288f..4435da1 100644 --- a/lunaix-os/hal/ahci/ahci_pci.c +++ b/lunaix-os/hal/ahci/ahci_pci.c @@ -1,30 +1,35 @@ #include +#include #include #include static int -ahci_pci_bind(struct device_def* def, struct device* dev) +ahci_pci_create(struct device_def* def, morph_t* morphed) { - struct pci_device* ahci_dev; + struct pci_probe* probe; + struct device* dev; struct pci_base_addr* bar6; struct ahci_driver* ahci_drv; msi_vector_t msiv; - ahci_dev = PCI_DEVICE(dev); - bar6 = pci_device_bar(ahci_dev, 5); + probe = changeling_try_reveal(morphed, pci_probe_morpher); + if (!probe) { + return EINVAL; + } + + bar6 = pci_device_bar(probe, 5); assert_msg(pci_bar_mmio_space(bar6), "AHCI: BAR#6 is not MMIO."); pci_reg_t cmd = 0; pci_cmd_set_bus_master(&cmd); pci_cmd_set_mmio(&cmd); pci_cmd_set_msi(&cmd); - pci_apply_command(ahci_dev, cmd); + pci_apply_command(probe, cmd); - assert(pci_capability_msi(ahci_dev)); + assert(pci_capability_msi(probe)); - msiv = isrm_msialloc(ahci_hba_isr); - pci_setup_msi(ahci_dev, msiv); + msiv = pci_msi_setup_simple(probe, ahci_hba_isr); struct ahci_driver_param param = { .mmio_base = bar6->start, @@ -33,30 +38,37 @@ ahci_pci_bind(struct device_def* def, struct device* dev) }; ahci_drv = ahci_driver_init(¶m); - pci_bind_instance(ahci_dev, ahci_drv); + dev = device_allocvol(NULL, ahci_drv); + + device_setname(dev_meta(dev), + "pci-ahci%d", devclass_mkvar(&def->class)); + + pci_bind_instance(probe, dev); return 0; } -static int -ahci_pci_init(struct device_def* def) +static bool +ahci_pci_compat(struct pci_probe* probe) { - return pci_bind_definition_all(pcidev_def(def)); + return pci_device_class(probe) == AHCI_HBA_CLASS; } -static bool -ahci_pci_compat(struct pci_device_def* def, - struct pci_device* pcidev) +static int +ahci_pci_register(struct device_def* def) { - return pci_device_class(pcidev) == AHCI_HBA_CLASS; + return !pci_register_driver(def, ahci_pci_compat); } -static struct pci_device_def ahcidef = { - .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA), - .name = "Generic AHCI", - .init = ahci_pci_init, - .bind = ahci_pci_bind }, - .test_compatibility = ahci_pci_compat +static struct device_def ahcidef = +{ + def_device_class(GENERIC, STORAGE, SATA), + def_device_name("Generic AHCI (pci-bus)"), + + def_on_register(ahci_pci_register), + def_on_create(ahci_pci_create), + + def_non_trivial }; -EXPORT_PCI_DEVICE(ahci, &ahcidef, load_postboot); \ No newline at end of file +EXPORT_DEVICE(ahci, &ahcidef, load_postboot); \ No newline at end of file diff --git a/lunaix-os/hal/bus/pci.c b/lunaix-os/hal/bus/pci.c index 6b13b94..3052a90 100644 --- a/lunaix-os/hal/bus/pci.c +++ b/lunaix-os/hal/bus/pci.c @@ -18,127 +18,151 @@ LOG_MODULE("PCI") -static DEFINE_LLIST(pci_devices); -static DECLARE_HASHTABLE(pci_devcache, 8); +/* + device instance for pci bridge, + currently, lunaix only support one bridge controller. +*/ +static struct device* pci_bridge; -static struct device_cat* pcidev_cat; -static struct device_def pci_def; - -void -pci_probe_msi_info(struct pci_device* device); +static morph_t* pci_probers; +static DECLARE_HASHTABLE(pci_drivers, 8); static inline void -pci_log_device(struct pci_device* pcidev) +pci_log_device(struct pci_probe* probe) { - pciaddr_t loc = pcidev->loc; - struct device_def* binddef = pcidev->binding.def; + pciaddr_t loc = probe->loc; kprintf("pci.%03d:%02d:%02d, class=%p, vendor:dev=%04x:%04x", PCILOC_BUS(loc), PCILOC_DEV(loc), PCILOC_FN(loc), - pcidev->class_info, - PCI_DEV_VENDOR(pcidev->device_info), - PCI_DEV_DEVID(pcidev->device_info)); + probe->class_info, + PCI_DEV_VENDOR(probe->device_info), + PCI_DEV_DEVID(probe->device_info)); } -static struct pci_device* -pci_create_device(pciaddr_t loc, ptr_t pci_base, int devinfo) +static void +__pci_probe_msi_info(struct pci_probe* probe) { - pci_reg_t class = pci_read_cspace(pci_base, 0x8); - - u32_t devid = PCI_DEV_DEVID(devinfo); - u32_t vendor = PCI_DEV_VENDOR(devinfo); - pci_reg_t intr = pci_read_cspace(pci_base, 0x3c); + // Note that Virtualbox have to use ICH9 chipset for MSI support. + // Qemu seems ok with default PIIX3, Bochs is pending to test... + // See https://www.virtualbox.org/manual/ch03.html (section 3.5.1) + pci_reg_t status = + pci_read_cspace(probe->cspace_base, PCI_REG_STATUS_CMD) >> 16; - struct pci_device* device = vzalloc(sizeof(struct pci_device)); - device->class_info = class; - device->device_info = devinfo; - device->cspace_base = pci_base; - device->intr_info = intr; + if (!(status & 0x10)) { + probe->msi_loc = 0; + return; + } - device_create(&device->dev, dev_meta(pcidev_cat), DEV_IFSYS, NULL); + pci_reg_t cap_ptr = pci_read_cspace(probe->cspace_base, 0x34) & 0xff; + u32_t cap_hdr; - pci_probe_msi_info(device); - pci_probe_bar_info(device); + while (cap_ptr) { + cap_hdr = pci_read_cspace(probe->cspace_base, cap_ptr); + if ((cap_hdr & 0xff) == 0x5) { + // MSI + probe->msi_loc = cap_ptr; + return; + } + cap_ptr = (cap_hdr >> 8) & 0xff; + } +} - llist_append(&pci_devices, &device->dev_chain); - register_device(&device->dev, &pci_def.class, "%x", loc); - pci_def.class.variant++; - return device; +static void +__pci_probe_bar_info(struct pci_probe* probe) +{ + u32_t bar; + struct pci_base_addr* ba; + for (size_t i = 0; i < PCI_BAR_COUNT; i++) { + ba = &probe->bar[i]; + ba->size = pci_bar_sizing(probe, &bar, i + 1); + if (PCI_BAR_MMIO(bar)) { + ba->start = PCI_BAR_ADDR_MM(bar); + ba->type |= PCI_BAR_CACHEABLE(bar) ? BAR_TYPE_CACHABLE : 0; + ba->type |= BAR_TYPE_MMIO; + } else { + ba->start = PCI_BAR_ADDR_IO(bar); + } + } } -int -pci_bind_definition(struct pci_device_def* pcidef, bool* more) +static void +__pci_add_prober(pciaddr_t loc, ptr_t pci_base, int devinfo) { - if (!pcidef->devdef.bind) { - ERROR("pcidev %xh:%xh.%d is unbindable", - pcidef->devdef.class.fn_grp, - pcidef->devdef.class.device, - pcidef->devdef.class.variant); - return EINVAL; - } + struct pci_probe* prober; + morph_t* probe_morph; - *more = false; + pci_reg_t class = pci_read_cspace(pci_base, 0x8); - bool bind_attempted = 0; - int errno = 0; + u32_t devid = PCI_DEV_DEVID(devinfo); + u32_t vendor = PCI_DEV_VENDOR(devinfo); + pci_reg_t intr = pci_read_cspace(pci_base, 0x3c); - struct device_def* devdef; - struct pci_device *pos, *n; - llist_for_each(pos, n, &pci_devices, dev_chain) - { - if (binded_pcidev(pos)) { - continue; - } + prober = vzalloc(sizeof(*prober)); - bool matched; + prober->class_info = class; + prober->device_info = devinfo; + prober->cspace_base = pci_base; + prober->intr_info = intr; + prober->loc = loc; - assert(pcidef->test_compatibility); - matched = pcidef->test_compatibility(pcidef, pos); + changeling_morph_anon(pci_probers, prober->mobj, pci_probe_morpher); - if (!matched) { - continue; - } + __pci_probe_msi_info(prober); + __pci_probe_bar_info(prober); - if (bind_attempted) { - *more = true; - break; - } + pci_log_device(prober); +} - bind_attempted = true; - devdef = &pcidef->devdef; - errno = devdef->bind(devdef, &pos->dev); +static int +__pci_bind(struct pci_registry* reg, struct pci_probe* probe) +{ + int errno; + struct device_def* devdef; - if (errno) { - ERROR("pci_loc:%x, bind (%xh:%xh.%d) failed, e=%d", - pos->loc, - devdef->class.fn_grp, - devdef->class.device, - devdef->class.variant, - errno); - continue; - } + if (probe->bind) { + return EEXIST; + } - pos->binding.def = &pcidef->devdef; + if (!reg->check_compact(probe)) { + return EINVAL; + } + + devdef = reg->definition; + errno = devdef->create(devdef, &probe->mobj); + + if (errno) { + ERROR("pci_loc:%x, bind (%xh:%xh.%d) failed, e=%d", + probe->loc, + devdef->class.fn_grp, + devdef->class.device, + devdef->class.variant, + errno); } return errno; } int -pci_bind_definition_all(struct pci_device_def* pcidef) +pci_bind_driver(struct pci_registry* reg) { - int e = 0; - bool more = false; - do { - if ((e = pci_bind_definition(pcidef, &more))) { - break; + struct pci_probe* probe; + int errno = 0; + + morph_t *pos, *n; + changeling_for_each(pos, n, pci_probers) + { + probe = changeling_reveal(pos, pci_probe_morpher); + + errno = __pci_bind(reg, probe); + if (errno) { + continue; } - } while (more); + } - return e; + return errno; } void @@ -166,169 +190,190 @@ pci_probe_device(pciaddr_t pci_loc) } } - struct pci_device *pos, *n; - hashtable_hash_foreach(pci_devcache, pci_loc, pos, n, dev_cache) + struct pci_probe* prober; + morph_t *pos, *n; + changeling_for_each(pos, n, pci_probers) { - if (pos->loc == pci_loc) { - pci_log_device(pos); + prober = changeling_reveal(pos, pci_probe_morpher); + if (prober->loc == pci_loc) { + pci_log_device(prober); return; } } - struct pci_device* pcidev = pci_create_device(pci_loc, base, reg1); - if (pcidev) { - pcidev->loc = pci_loc; - hashtable_hash_in(pci_devcache, &pcidev->dev_cache, pci_loc); - pci_log_device(pcidev); + __pci_add_prober(pci_loc, base, reg1); +} + +static struct pci_registry* +__pci_registry_get(struct device_def* def) +{ + struct pci_registry *pos, *n; + unsigned int hash; + + hash = hash_32(__ptr(def), HSTR_FULL_HASH); + hashtable_hash_foreach(pci_drivers, hash, pos, n, entries) + { + if (pos->definition == def) { + return pos; + } } + + return NULL; } -void -pci_scan() +static int +__pci_proxied_devdef_load(struct device_def* def) { - for (u32_t loc = 0; loc < (pciaddr_t)-1; loc += 8) { - pci_probe_device((pciaddr_t)loc); + struct pci_registry* reg; + int errno = 0; + + reg = __pci_registry_get(def); + assert(reg); + + return pci_bind_driver(reg); +} + +bool +pci_register_driver(struct device_def* def, pci_id_checker_t checker) +{ + struct pci_registry* reg; + unsigned int hash; + + if (!checker) { + return false; + } + + if (__pci_registry_get(def)) { + return false; } + + reg = valloc(sizeof(*reg)); + + *reg = (struct pci_registry) { + .check_compact = checker, + .definition = def, + }; + + device_chain_loader(def, __pci_proxied_devdef_load); + + hash = hash_32(__ptr(def), HSTR_FULL_HASH); + hashtable_hash_in(pci_drivers, ®->entries, hash); + + return true; } void -pci_probe_bar_info(struct pci_device* device) +pci_scan() { - u32_t bar; - struct pci_base_addr* ba; - for (size_t i = 0; i < PCI_BAR_COUNT; i++) { - ba = &device->bar[i]; - ba->size = pci_bar_sizing(device, &bar, i + 1); - if (PCI_BAR_MMIO(bar)) { - ba->start = PCI_BAR_ADDR_MM(bar); - ba->type |= PCI_BAR_CACHEABLE(bar) ? BAR_TYPE_CACHABLE : 0; - ba->type |= BAR_TYPE_MMIO; - } else { - ba->start = PCI_BAR_ADDR_IO(bar); - } + for (u32_t loc = 0; loc < (pciaddr_t)-1; loc += 8) { + pci_probe_device((pciaddr_t)loc); } } -void -pci_setup_msi(struct pci_device* device, msi_vector_t msiv) +static void +__pci_config_msi(struct pci_probe* probe, msi_vector_t msiv) { // 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); - pci_reg_t reg1 = pci_read_cspace(device->cspace_base, device->msi_loc); + pci_reg_t reg1 = pci_read_cspace(probe->cspace_base, probe->msi_loc); pci_reg_t msg_ctl = reg1 >> 16; int offset_cap64 = !!(msg_ctl & MSI_CAP_64BIT) * 4; - pci_write_cspace(device->cspace_base, - PCI_MSI_ADDR_LO(device->msi_loc), + pci_write_cspace(probe->cspace_base, + PCI_MSI_ADDR_LO(probe->msi_loc), msi_addr); if (offset_cap64) { - pci_write_cspace(device->cspace_base, - PCI_MSI_ADDR_HI(device->msi_loc), + pci_write_cspace(probe->cspace_base, + PCI_MSI_ADDR_HI(probe->msi_loc), (u64_t)msi_addr >> 32); } - pci_write_cspace(device->cspace_base, - PCI_MSI_DATA(device->msi_loc, offset_cap64), + pci_write_cspace(probe->cspace_base, + PCI_MSI_DATA(probe->msi_loc, offset_cap64), msi_data & 0xffff); if ((msg_ctl & MSI_CAP_MASK)) { pci_write_cspace( - device->cspace_base, PCI_MSI_MASK(device->msi_loc, offset_cap64), 0); + probe->cspace_base, PCI_MSI_MASK(probe->msi_loc, offset_cap64), 0); } // manipulate the MSI_CTRL to allow device using MSI to request service. reg1 = (reg1 & 0xff8fffff) | 0x10000; - pci_write_cspace(device->cspace_base, device->msi_loc, reg1); + pci_write_cspace(probe->cspace_base, probe->msi_loc, reg1); } -void -pci_probe_msi_info(struct pci_device* device) +msienv_t +pci_msi_start(struct pci_probe* probe) { - // Note that Virtualbox have to use ICH9 chipset for MSI support. - // Qemu seems ok with default PIIX3, Bochs is pending to test... - // See https://www.virtualbox.org/manual/ch03.html (section 3.5.1) - pci_reg_t status = - pci_read_cspace(device->cspace_base, PCI_REG_STATUS_CMD) >> 16; + /* + 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)); - if (!(status & 0x10)) { - device->msi_loc = 0; - return; - } + return env; +} - pci_reg_t cap_ptr = pci_read_cspace(device->cspace_base, 0x34) & 0xff; - u32_t cap_hdr; +msi_vector_t +pci_msi_setup_at(msienv_t msienv, struct pci_probe* probe, + int i, isr_cb handler) +{ + msi_vector_t msiv; - while (cap_ptr) { - cap_hdr = pci_read_cspace(device->cspace_base, cap_ptr); - if ((cap_hdr & 0xff) == 0x5) { - // MSI - device->msi_loc = cap_ptr; - return; - } - cap_ptr = (cap_hdr >> 8) & 0xff; - } + msiv = isrm_msi_alloc(msienv, 0, i, handler); + __pci_config_msi(probe, msiv); + + return msiv; } size_t -pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num) +pci_bar_sizing(struct pci_probe* probe, u32_t* bar_out, u32_t bar_num) { - pci_reg_t bar = pci_read_cspace(dev->cspace_base, PCI_REG_BAR(bar_num)); + pci_reg_t sized, bar; + + bar = pci_read_cspace(probe->cspace_base, PCI_REG_BAR(bar_num)); if (!bar) { *bar_out = 0; return 0; } - pci_write_cspace(dev->cspace_base, PCI_REG_BAR(bar_num), 0xffffffff); - pci_reg_t sized = - pci_read_cspace(dev->cspace_base, PCI_REG_BAR(bar_num)) & ~0x1; + pci_write_cspace(probe->cspace_base, PCI_REG_BAR(bar_num), 0xffffffff); + + sized = + pci_read_cspace(probe->cspace_base, PCI_REG_BAR(bar_num)) & ~0x1; + if (PCI_BAR_MMIO(bar)) { sized = PCI_BAR_ADDR_MM(sized); } + *bar_out = bar; - pci_write_cspace(dev->cspace_base, PCI_REG_BAR(bar_num), bar); + pci_write_cspace(probe->cspace_base, PCI_REG_BAR(bar_num), bar); + return ~sized + 1; } -struct pci_device* -pci_get_device_by_id(u16_t vendorId, u16_t deviceId) -{ - u32_t dev_info = vendorId | (deviceId << 16); - struct pci_device *pos, *n; - llist_for_each(pos, n, &pci_devices, dev_chain) - { - if (pos->device_info == dev_info) { - return pos; - } - } - - return NULL; -} - -struct pci_device* -pci_get_device_by_class(u32_t class) -{ - struct pci_device *pos, *n; - llist_for_each(pos, n, &pci_devices, dev_chain) - { - if (PCI_DEV_CLASS(pos->class_info) == class) { - return pos; - } - } - - return NULL; -} - void -pci_apply_command(struct pci_device* pcidev, pci_reg_t cmd) +pci_apply_command(struct pci_probe* probe, pci_reg_t cmd) { pci_reg_t rcmd; ptr_t base; - base = pcidev->cspace_base; + base = probe->cspace_base; rcmd = pci_read_cspace(base, PCI_REG_STATUS_CMD); cmd = cmd & 0xffff; @@ -340,11 +385,13 @@ pci_apply_command(struct pci_device* pcidev, pci_reg_t cmd) static void __pci_read_cspace(struct twimap* map) { - struct pci_device* pcidev = (struct pci_device*)(map->data); + struct pci_probe* probe; + + probe = twimap_data(map, struct pci_probe*); for (size_t i = 0; i < 256; i += sizeof(pci_reg_t)) { *(pci_reg_t*)(map->buffer + i) = - pci_read_cspace(pcidev->cspace_base, i); + pci_read_cspace(probe->cspace_base, i); } map->size_acc = 256; @@ -355,32 +402,42 @@ __pci_read_cspace(struct twimap* map) static void __pci_read_revid(struct twimap* map) { - int class = twimap_data(map, struct pci_device*)->class_info; - twimap_printf(map, "0x%x", PCI_DEV_REV(class)); + struct pci_probe* probe; + + probe = twimap_data(map, struct pci_probe*); + twimap_printf(map, "0x%x", PCI_DEV_REV(probe->class_info)); } static void __pci_read_class(struct twimap* map) { - int class = twimap_data(map, struct pci_device*)->class_info; - twimap_printf(map, "0x%x", PCI_DEV_CLASS(class)); + struct pci_probe* probe; + + probe = twimap_data(map, struct pci_probe*); + twimap_printf(map, "0x%x", PCI_DEV_CLASS(probe->class_info)); } static void __pci_read_devinfo(struct twimap* map) { - int devinfo = twimap_data(map, struct pci_device*)->device_info; - twimap_printf( - map, "%x:%x", PCI_DEV_VENDOR(devinfo), PCI_DEV_DEVID(devinfo)); + struct pci_probe* probe; + + probe = twimap_data(map, struct pci_probe*); + twimap_printf(map, "%x:%x", + PCI_DEV_VENDOR(probe->device_info), + PCI_DEV_DEVID(probe->device_info)); } static void __pci_bar_read(struct twimap* map) { - struct pci_device* pcidev = twimap_data(map, struct pci_device*); - int bar_index = twimap_index(map, int); + struct pci_probe* probe; + int bar_index; + + probe = twimap_data(map, struct pci_probe*); + bar_index = twimap_index(map, int); - struct pci_base_addr* bar = &pcidev->bar[bar_index]; + struct pci_base_addr* bar = &probe->bar[bar_index]; if (!bar->start && !bar->size) { twimap_printf(map, "[%d] not present \n", bar_index); @@ -415,17 +472,20 @@ __pci_bar_gonext(struct twimap* map) static void __pci_read_binding(struct twimap* map) { - struct pci_device* pcidev = twimap_data(map, struct pci_device*); - struct device_def* devdef = pcidev->binding.def; - if (!devdef) { + struct pci_probe* probe; + struct devident* devid; + + probe = twimap_data(map, struct pci_probe*); + if (!probe->bind) { return; } - twimap_printf(map, - "%xh:%xh.%d", - devdef->class.fn_grp, - devdef->class.device, - devdef->class.variant); + devid = &probe->bind->ident; + + twimap_printf(map, "%xh:%xh.%d", + devid->fn_grp, + DEV_KIND_FROM(devid->unique), + DEV_VAR_FROM(devid->unique)); } static void @@ -438,29 +498,32 @@ void pci_build_fsmapping() { struct twifs_node *pci_class = twifs_dir_node(NULL, "pci"), *pci_dev; - struct pci_device *pos, *n; struct twimap* map; + struct pci_probe* probe; + morph_t *pos, *n; - map = twifs_mapping(pci_class, NULL, "rescan"); - map->read = __pci_trigger_bus_rescan; + // TODO bus rescan is not ready yet + // map = twifs_mapping(pci_class, NULL, "rescan"); + // map->read = __pci_trigger_bus_rescan; - llist_for_each(pos, n, &pci_devices, dev_chain) + changeling_for_each(pos, n, pci_probers) { - pci_dev = twifs_dir_node(pci_class, "%x", pos->loc); + probe = changeling_reveal(pos, pci_probe_morpher); + pci_dev = twifs_dir_node(pci_class, "%x", probe->loc); - map = twifs_mapping(pci_dev, pos, "config"); + map = twifs_mapping(pci_dev, probe, "config"); map->read = __pci_read_cspace; - map = twifs_mapping(pci_dev, pos, "revision"); + map = twifs_mapping(pci_dev, probe, "revision"); map->read = __pci_read_revid; - map = twifs_mapping(pci_dev, pos, "class"); + map = twifs_mapping(pci_dev, probe, "class"); map->read = __pci_read_class; - map = twifs_mapping(pci_dev, pos, "binding"); + map = twifs_mapping(pci_dev, probe, "binding"); map->read = __pci_read_binding; - map = twifs_mapping(pci_dev, pos, "io_bases"); + map = twifs_mapping(pci_dev, probe, "io_bases"); map->read = __pci_bar_read; map->go_next = __pci_bar_gonext; } @@ -470,25 +533,35 @@ EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping); /*---------- PCI 3.0 HBA device definition ----------*/ static int -pci_load_devices(struct device_def* def) +pci_register(struct device_def* def) { - pcidev_cat = device_addcat(NULL, "pci"); - - pci_scan(); + pci_probers = changeling_spawn(NULL, "pci_realm"); return 0; } -void -pci_bind_instance(struct pci_device* pcidev, void* devobj) +static int +pci_create(struct device_def* def, morph_t* obj) { - pcidev->dev.underlay = devobj; - pcidev->binding.dev = devobj; + 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); + + register_device(pci_bridge, &def->class, "pci_bridge"); + + pci_scan(); + + return 0; } static struct device_def pci_def = { - .name = "Generic PCI", - .class = DEVCLASS(DEVIF_SOC, DEVFN_BUSIF, DEV_PCI), - .init = pci_load_devices + def_device_name("Generic PCI"), + def_device_class(GENERIC, BUSIF, PCI), + + def_on_register(pci_register), + def_on_create(pci_create) }; EXPORT_DEVICE(pci3hba, &pci_def, load_sysconf); diff --git a/lunaix-os/hal/char/devnull.c b/lunaix-os/hal/char/devnull.c index 77650b0..3991548 100644 --- a/lunaix-os/hal/char/devnull.c +++ b/lunaix-os/hal/char/devnull.c @@ -30,7 +30,7 @@ __null_rd(struct device* dev, void* buf, size_t offset, size_t len) } static int -pdev_nulldev_init(struct device_def* def) +pdev_nulldev_create(struct device_def* def, morph_t* obj) { struct device* devnull = device_allocseq(NULL, NULL); devnull->ops.write_page = __null_wr_pg; @@ -44,7 +44,8 @@ pdev_nulldev_init(struct device_def* def) } static struct device_def devnull_def = { - .name = "null", - .class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_NULL, DEV_BUILTIN_NULL), - .init = pdev_nulldev_init}; + def_device_name("edendi"), + def_device_class(LUNAIX, PSEUDO, NIHIL), + def_on_create(pdev_nulldev_create) +}; EXPORT_DEVICE(nulldev, &devnull_def, load_onboot); diff --git a/lunaix-os/hal/char/devzero.c b/lunaix-os/hal/char/devzero.c index c637a34..3eb9ea4 100644 --- a/lunaix-os/hal/char/devzero.c +++ b/lunaix-os/hal/char/devzero.c @@ -18,7 +18,7 @@ __zero_rd(struct device* dev, void* buf, size_t offset, size_t len) } static int -pdev_zerodev_init(struct device_def* def) +pdev_zerodev_create(struct device_def* def, morph_t* obj) { struct device* devzero = device_allocseq(NULL, NULL); devzero->ops.read_page = __zero_rd_pg; @@ -30,7 +30,8 @@ pdev_zerodev_init(struct device_def* def) } static struct device_def devzero_def = { - .name = "zero", - .class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_ZERO, DEV_BUILTIN_ZERO), - .init = pdev_zerodev_init}; + def_device_name("nihil"), + def_device_class(LUNAIX, PSEUDO, ZERO), + def_on_create(pdev_zerodev_create) +}; EXPORT_DEVICE(zerodev, &devzero_def, load_onboot); diff --git a/lunaix-os/hal/char/lxconsole.c b/lunaix-os/hal/char/lxconsole.c index 4922297..aa4136a 100644 --- a/lunaix-os/hal/char/lxconsole.c +++ b/lunaix-os/hal/char/lxconsole.c @@ -27,7 +27,7 @@ struct console { - struct capability_meta* tp_cap; + struct potens_meta* tp_cap; struct lx_timer* flush_timer; struct fifo_buf output; struct fifo_buf input; @@ -92,8 +92,8 @@ __lxconsole_listener(struct input_device* dev) fifo_putone(&lx_console.input, ttychr); - struct termport_capability* tpcap; - tpcap = get_capability(lx_console.tp_cap, typeof(*tpcap)); + struct termport_potens* tpcap; + tpcap = get_potens(lx_console.tp_cap, typeof(*tpcap)); term_notify_data_avaliable(tpcap); pwake_all(&lx_reader); @@ -298,24 +298,16 @@ lxconsole_spawn_ttydev(struct device_def* devdef) waitq_init(&lx_reader); input_add_listener(__lxconsole_listener); - struct termport_capability* tp_cap; - - tp_cap = new_capability(TERMPORT_CAP, struct termport_capability); - term_cap_set_operations(tp_cap, termport_default_ops); - - lx_console.tp_cap = cap_meta(tp_cap); - device_grant_capability(tty_dev, lx_console.tp_cap); - register_device(tty_dev, &devdef->class, "vcon"); - term_create(tty_dev, "VCON"); + term_attach_potens(tty_dev, NULL, "VCON"); return 0; } static struct device_def lxconsole_def = { - .name = "Lunaix Virtual Console", - .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN), - .init = lxconsole_spawn_ttydev + def_device_name("Lunaix Virtual Console"), + def_device_class(LUNAIX, TTY, VTERM), + def_on_load(lxconsole_spawn_ttydev) }; EXPORT_DEVICE(lxconsole, &lxconsole_def, load_onboot); \ No newline at end of file diff --git a/lunaix-os/hal/char/serial.c b/lunaix-os/hal/char/serial.c index d3d14c7..7943bb3 100644 --- a/lunaix-os/hal/char/serial.c +++ b/lunaix-os/hal/char/serial.c @@ -8,7 +8,6 @@ #include #include -#include LOG_MODULE("serial") @@ -47,9 +46,7 @@ serial_end_recv(struct serial_dev* sdev) pwake_one(&sdev->wq_rxdone); - struct termport_capability* tpcap; - tpcap = get_capability(sdev->tp_cap, typeof(*tpcap)); - term_notify_data_avaliable(tpcap); + term_notify_data_avaliable(sdev->tp_cap); } void @@ -256,7 +253,7 @@ __serial_set_cntrl_mode(struct device* dev, tcflag_t cflag) #define RXBUF_SIZE 512 -static struct termport_cap_ops tpcap_ops = { +static struct termport_pot_ops tppot_ops = { .set_cntrl_mode = __serial_set_cntrl_mode, .set_clkbase = __serial_set_baseclk, .set_speed = __serial_set_speed @@ -265,8 +262,12 @@ static struct termport_cap_ops tpcap_ops = { struct serial_dev* serial_create(struct devclass* class, char* if_ident) { - struct serial_dev* sdev = vzalloc(sizeof(struct serial_dev)); - struct device* dev = device_allocseq(dev_meta(serial_cat), sdev); + struct serial_dev* sdev; + struct device* dev; + + sdev = vzalloc(sizeof(struct serial_dev)); + dev = device_allocseq(dev_meta(serial_cat), sdev); + dev->ops.read = __serial_read; dev->ops.read_page = __serial_read_page; dev->ops.read_async = __serial_read_async; @@ -279,27 +280,18 @@ serial_create(struct devclass* class, char* if_ident) sdev->dev = dev; dev->underlay = sdev; - struct termport_capability* tp_cap = - new_capability(TERMPORT_CAP, struct termport_capability); - - term_cap_set_operations(tp_cap, &tpcap_ops); - sdev->tp_cap = cap_meta(tp_cap); - waitq_init(&sdev->wq_rxdone); waitq_init(&sdev->wq_txdone); rbuffer_init(&sdev->rxbuf, valloc(RXBUF_SIZE), RXBUF_SIZE); llist_append(&serial_devs, &sdev->sdev_list); - device_grant_capability(dev, cap_meta(tp_cap)); - - register_device(dev, class, "%s%d", if_ident, class->variant); - - term_create(dev, if_ident); + register_device_var(dev, class, "%s", if_ident); INFO("interface: %s, %xh:%xh.%d", dev->name_val, class->fn_grp, class->device, class->variant); - class->variant++; + sdev->tp_cap = term_attach_potens(dev, &tppot_ops, if_ident); + return sdev; } diff --git a/lunaix-os/hal/char/uart/16x50_dev.c b/lunaix-os/hal/char/uart/16x50_dev.c new file mode 100644 index 0000000..326fede --- /dev/null +++ b/lunaix-os/hal/char/uart/16x50_dev.c @@ -0,0 +1,44 @@ +#include + +#include + +#include "16x50.h" + +extern_hook_load(isa16x50_create_once); +extern_hook_create(pci16650_pci_create); +extern_hook_register(pci16x50_pci_register); + +static int +uart_16x50_load(struct device_def* def) +{ + isa16x50_create_once(def); + return 0; +} + +static int +uart_16x50_create(struct device_def* def, morph_t* morphed) +{ + if (morph_type_of(morphed, pci_probe_morpher)) { + pci16650_pci_create(def, morphed); + } + + return 0; +} + +static int +uart_16x50_register(struct device_def* def) +{ + pci16x50_pci_register(def); + + return 0; +} + +static struct device_def uart_dev = { + def_device_class(GENERIC, CHAR, UART16550), + def_device_name("16550 UART"), + + def_on_register(uart_16x50_register), + def_on_load(uart_16x50_load), + def_on_create(uart_16x50_create) +}; +EXPORT_DEVICE(uart16550_pmio, &uart_dev, load_onboot); \ No newline at end of file diff --git a/lunaix-os/hal/char/uart/16x50_isa.c b/lunaix-os/hal/char/uart/16x50_isa.c index 414dc33..3958223 100644 --- a/lunaix-os/hal/char/uart/16x50_isa.c +++ b/lunaix-os/hal/char/uart/16x50_isa.c @@ -17,8 +17,8 @@ com_irq_handler(const struct hart_state* hstate) uart_handle_irq_overlap(vector, &com_ports); } -static int -upiom_init(struct device_def* def) +int +isa16x50_create_once(struct device_def* def) { int irq3 = 3, irq4 = 4; u16_t ioports[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 }; @@ -54,11 +54,4 @@ upiom_init(struct device_def* def) } return 0; -} - -static struct device_def uart_pmio_def = { - .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_UART16550), - .name = "16550 UART (pmio, isa-bus)", - .init = upiom_init -}; -EXPORT_DEVICE(uart16550_pmio, &uart_pmio_def, load_onboot); \ No newline at end of file +} \ No newline at end of file diff --git a/lunaix-os/hal/char/uart/16x50_pci.c b/lunaix-os/hal/char/uart/16x50_pci.c index 59aac6c..20beda1 100644 --- a/lunaix-os/hal/char/uart/16x50_pci.c +++ b/lunaix-os/hal/char/uart/16x50_pci.c @@ -13,6 +13,7 @@ LOG_MODULE("16x50-pci") static DEFINE_LLIST(pci_ports); + static void uart_msi_irq_handler(const struct hart_state* hstate) { @@ -33,32 +34,31 @@ uart_intx_irq_handler(const struct hart_state* hstate) uart_handle_irq_overlap(vector, &pci_ports); } -static int -pci16550_init(struct device_def* def) -{ - return pci_bind_definition_all(pcidev_def(def)); -} - static bool -pci16650_check_compat(struct pci_device_def* def, - struct pci_device* pcidev) +pci16x50_check_compat(struct pci_probe* probe) { unsigned int classid; - classid = pci_device_class(pcidev); + classid = pci_device_class(probe); return (classid & 0xffff00) == PCI_DEVICE_16x50_UART; } -static int -pci16650_binder(struct device_def* def, struct device* dev) +int +pci16x50_pci_register(struct device_def* def) +{ + return !pci_register_driver(def, pci16x50_check_compat); +} + +int +pci16x50_pci_create(struct device_def* def, morph_t* obj) { struct pci_base_addr* bar; - struct pci_device* pcidev; + struct pci_probe* probe; struct uart16550* uart; struct serial_dev* sdev; msi_vector_t msiv; - pcidev = PCI_DEVICE(dev); + probe = changeling_reveal(obj, pci_probe_morpher); pci_reg_t cmd = 0; @@ -67,7 +67,7 @@ pci16650_binder(struct device_def* def, struct device* dev) cmd = 0; pci_cmd_set_msi(&cmd); - bar = pci_device_bar(pcidev, i); + bar = pci_device_bar(probe, i); if (bar->size == 0) { continue; } @@ -75,17 +75,17 @@ pci16650_binder(struct device_def* def, struct device* dev) if (!pci_bar_mmio_space(bar)) { #ifdef CONFIG_PCI_PMIO pci_cmd_set_pmio(&cmd); - pci_apply_command(pcidev, cmd); + pci_apply_command(probe, cmd); uart = uart16x50_pmio_create(bar->start); #else - WARN("plaform configured to not support pmio access.") + WARN("plaform configured to not support pmio access."); continue; #endif } else { pci_cmd_set_mmio(&cmd); - pci_apply_command(pcidev, cmd); + pci_apply_command(probe, cmd); uart = uart16x50_mmio_create(bar->start, bar->size); } @@ -95,35 +95,26 @@ pci16650_binder(struct device_def* def, struct device* dev) continue; } - if (!pci_capability_msi(pcidev)) { + if (!pci_capability_msi(probe)) { WARN("failed to fallback to legacy INTx: not supported."); continue; } - msiv = isrm_msialloc(uart_msi_irq_handler); + 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)); - pci_setup_msi(pcidev, msiv); INFO("base: 0x%x (%s), irq=%d (%s)", bar->start, pci_bar_mmio_space(bar) ? "mmio" : "pmio", msi_vect(msiv), - pci_capability_msi(pcidev) ? "msi" : "intx, re-routed"); + pci_capability_msi(probe) ? "msi" : "intx, re-routed"); uart->iv = msi_vect(msiv); - sdev = uart_create_serial(uart, &def->class, &pci_ports, "PCI"); - pci_bind_instance(pcidev, sdev); + pci_bind_instance(probe, sdev->dev); } return 0; } - -static struct pci_device_def uart_pci_def = { - .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_CHAR, DEV_UART16550), - .name = "16550 UART (PCI/MMIO)", - .init = pci16550_init, - .bind = pci16650_binder }, - .test_compatibility = pci16650_check_compat -}; -EXPORT_PCI_DEVICE(uart16550_pci, &uart_pci_def, load_onboot); \ No newline at end of file diff --git a/lunaix-os/hal/char/uart/LBuild b/lunaix-os/hal/char/uart/LBuild index 83088c6..9ed3119 100644 --- a/lunaix-os/hal/char/uart/LBuild +++ b/lunaix-os/hal/char/uart/LBuild @@ -2,6 +2,7 @@ sources([ "16x50_base.c", "16x50_pmio.c", "16x50_mmio.c", + "16x50_dev.c", ]) if config("xt_16x50"): diff --git a/lunaix-os/hal/devtree/LBuild b/lunaix-os/hal/devtree/LBuild new file mode 100644 index 0000000..4709a35 --- /dev/null +++ b/lunaix-os/hal/devtree/LBuild @@ -0,0 +1,5 @@ +sources([ + "dt_interrupt.c", + "dt.c", + "dtm.c" +]) \ No newline at end of file diff --git a/lunaix-os/hal/devtree/devtree.h b/lunaix-os/hal/devtree/devtree.h index 3b1df08..c2374c8 100644 --- a/lunaix-os/hal/devtree/devtree.h +++ b/lunaix-os/hal/devtree/devtree.h @@ -3,6 +3,44 @@ #include +#include + +static inline bool +propeq(struct fdt_iter* it, const char* key) +{ + return streq(fdtit_prop_key(it), key); +} + +static inline void +__mkprop_val32(struct fdt_iter* it, struct dt_prop_val* val) +{ + val->u32_val = le(*(u32_t*)&it->prop[1]); + val->size = le(it->prop->len); +} + +static inline void +__mkprop_val64(struct fdt_iter* it, struct dt_prop_val* val) +{ + val->u64_val = le64(*(u64_t*)&it->prop[1]); + val->size = le(it->prop->len); +} + +static inline void +__mkprop_ptr(struct fdt_iter* it, struct dt_prop_val* val) +{ + val->ptr_val = __ptr(&it->prop[1]); + val->size = le(it->prop->len); +} + +static inline u32_t +__prop_getu32(struct fdt_iter* it) +{ + return le(*(u32_t*)&it->prop[1]); +} + +bool +parse_stdintr_prop(struct fdt_iter* it, struct dt_intr_node* node); + bool parse_stdintr_prop(struct fdt_iter* it, struct dt_intr_node* node); diff --git a/lunaix-os/hal/devtree/dt.c b/lunaix-os/hal/devtree/dt.c index 72c443c..f1d6860 100644 --- a/lunaix-os/hal/devtree/dt.c +++ b/lunaix-os/hal/devtree/dt.c @@ -1,12 +1,12 @@ #include #include - -#include +#include #include "devtree.h" LOG_MODULE("dtb") +static morph_t* devtree_obj_root; static struct dt_context dtctx; void @@ -126,39 +126,6 @@ fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi) rsvdi->block = NULL; } -static inline bool -propeq(struct fdt_iter* it, const char* key) -{ - return streq(fdtit_prop_key(it), key); -} - -static inline void -__mkprop_val32(struct fdt_iter* it, struct dt_prop_val* val) -{ - val->u32_val = le(*(u32_t*)&it->prop[1]); - val->size = le(it->prop->len); -} - -static inline void -__mkprop_val64(struct fdt_iter* it, struct dt_prop_val* val) -{ - val->u64_val = le64(*(u64_t*)&it->prop[1]); - val->size = le(it->prop->len); -} - -static inline void -__mkprop_ptr(struct fdt_iter* it, struct dt_prop_val* val) -{ - val->ptr_val = __ptr(&it->prop[1]); - val->size = le(it->prop->len); -} - -static inline u32_t -__prop_getu32(struct fdt_iter* it) -{ - return le(*(u32_t*)&it->prop[1]); -} - static bool __parse_stdbase_prop(struct fdt_iter* it, struct dt_node_base* node) { @@ -169,15 +136,9 @@ __parse_stdbase_prop(struct fdt_iter* it, struct dt_node_base* node) if (propeq(it, "compatible")) { __mkprop_ptr(it, &node->compat); } - - else if (propeq(it, "model")) { - node->model = (const char*)&prop[1]; - } else if (propeq(it, "phandle")) { node->phandle = __prop_getu32(it); - hashtable_hash_in(dtctx.phnds_table, - &node->phnd_link, node->phandle); } else if (propeq(it, "#address-cells")) { @@ -263,6 +224,25 @@ __parse_stdflags(struct fdt_iter* it, struct dt_node_base* node) return true; } +static inline void +__dt_node_set_name(struct dt_node_base* node, const char* name) +{ + changeling_setname(&node->mobj, name); +} + +static inline void +__init_prop_table(struct dt_node_base* node) +{ + struct dt_prop_table* propt; + + propt = valloc(sizeof(*propt)); + hashtable_init(propt->_op_bucket); +} + +#define prop_table_add(node, prop) \ + hashtable_hash_in( (node)->props->_op_bucket, \ + &(prop)->ht, (prop)->key.hash); + static void __parse_other_prop(struct fdt_iter* it, struct dt_node_base* node) { @@ -277,9 +257,8 @@ __parse_other_prop(struct fdt_iter* it, struct dt_node_base* node) __mkprop_ptr(it, &prop->val); hstr_rehash(&prop->key, HSTR_FULL_HASH); - hash = prop->key.hash; - hashtable_hash_in(node->_op_bucket, &prop->ht, hash); + prop_table_add(node, prop); } static void @@ -297,7 +276,7 @@ __fill_node(struct fdt_iter* it, struct dt_node* node) return; } - if (__parse_stdintr_prop(it, &node->intr)) { + if (parse_stdintr_prop(it, &node->intr)) { return; } @@ -332,11 +311,16 @@ __fill_root(struct fdt_iter* it, struct dt_root* node) static inline void __init_node(struct dt_node_base* node) { - hashtable_init(node->_op_bucket); - llist_init_head(&node->children); + morph_t* parent; - if (node->parent) + parent = devtree_obj_root; + if (node->parent) { + parent = node->mobj.parent; node->_std = node->parent->_std; + } + + __init_prop_table(node); + changeling_morph_anon(parent, node->mobj, dt_morpher); } static inline void @@ -488,12 +472,11 @@ dt_load(ptr_t dtb_dropoff) node->parent = prev; __init_node_regular((struct dt_node*)node); - llist_append(&prev->children, &node->siblings); llist_append(&dtctx.nodes, &node->nodes); } - node->name = (const char*)&it.pos[1]; + __dt_node_set_name(node, (const char*)&it.pos[1]); } if (unlikely(is_root_level)) { @@ -520,7 +503,7 @@ struct dt_node* dt_resolve_phandle(dt_phnd_t phandle) { struct dt_node_base *pos, *n; - hashtable_hash_foreach(dtctx.phnds_table, phandle, pos, n, phnd_link) + llist_for_each(pos, n, &dtctx.nodes, nodes) { if (pos->phandle == phandle) { return (struct dt_node*)pos; @@ -534,7 +517,7 @@ static bool __byname_predicate(struct dt_node_iter* iter, struct dt_node_base* node) { int i = 0; - const char* be_matched = node->name; + const char* be_matched = HSTR_VAL(node->mobj.name); const char* name = (const char*)iter->closure; while (be_matched[i] && name[i]) @@ -567,11 +550,13 @@ dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, iter->closure = closure; iter->pred = pred; - struct dt_node_base *pos, *n; - llist_for_each(pos, n, &node->base.children, siblings) + morph_t *pos, *n; + struct dt_node_base* base; + changeling_for_each(pos, n, &node->mobj) { - if (pred(iter, pos)) { - iter->matched = pos; + base = &changeling_reveal(pos, dt_morpher)->base; + if (pred(iter, base)) { + iter->matched = base; break; } } @@ -585,21 +570,23 @@ dt_find_next(struct dt_node_iter* iter, return false; } - struct dt_node_base *pos, *head; + struct dt_node *node; + morph_t *pos, *head; - head = iter->head; - pos = iter->matched; - *matched = pos; + head = dt_mobj(iter->head); + pos = dt_mobj(iter->matched); + *matched = iter->matched; - while (&pos->siblings != &head->children) + while (&pos->sibs != &head->subs) { - pos = list_next(pos, struct dt_node_base, siblings); + pos = list_next(pos, morph_t, sibs); + node = changeling_reveal(pos, dt_morpher); - if (!iter->pred(iter, pos)) { + if (!iter->pred(iter, &node->base)) { continue; } - iter->matched = pos; + iter->matched = &node->base; return true; } @@ -617,7 +604,7 @@ dt_getprop(struct dt_node_base* base, const char* name) hstr_rehash(&hashed_name, HSTR_FULL_HASH); hash = hashed_name.hash; - hashtable_hash_foreach(base->_op_bucket, hash, pos, n, ht) + hashtable_hash_foreach(base->props->_op_bucket, hash, pos, n, ht) { if (HSTR_EQ(&pos->key, &hashed_name)) { return &pos->val; @@ -625,4 +612,17 @@ dt_getprop(struct dt_node_base* base, const char* name) } return NULL; -} \ No newline at end of file +} + +struct dt_context* +dt_main_context() +{ + return &dtctx; +} + +static void +__init_devtree() +{ + devtree_obj_root = changeling_spawn(NULL, NULL); +} +owloysius_fetch_init(__init_devtree, on_sysconf); \ No newline at end of file diff --git a/lunaix-os/hal/devtree/dt_interrupt.c b/lunaix-os/hal/devtree/dt_interrupt.c index e6ad3ca..ab4d8b3 100644 --- a/lunaix-os/hal/devtree/dt_interrupt.c +++ b/lunaix-os/hal/devtree/dt_interrupt.c @@ -46,7 +46,7 @@ __interrupt_keysize(struct dt_node_base* base) static void __mask_key(struct dt_intr_mapkey* k, struct dt_intr_mapkey* mask) { - for (int i = 0; i < k->size; i++) + for (unsigned int i = 0; i < k->size; i++) { k->val[i] &= mask->val[i]; } @@ -59,7 +59,7 @@ __compare_key(struct dt_intr_mapkey* k1, struct dt_intr_mapkey* k2) return false; } - for (int i = 0; i < k1->size; i++) + for (unsigned int i = 0; i < k1->size; i++) { if (k1->val[i] != k2->val[i]) { return false; @@ -173,11 +173,13 @@ dt_resolve_interrupt(struct dt_node* node) llist_for_each(pos, n, &i_nexus->map->mapent, ents) { if (__compare_key(&pos->key, &key)) { + __destory_key(&key); return &pos->parent_props; } } __destory_key(&key); + return NULL; } bool diff --git a/lunaix-os/hal/devtree/dtm.c b/lunaix-os/hal/devtree/dtm.c new file mode 100644 index 0000000..69ec2e5 --- /dev/null +++ b/lunaix-os/hal/devtree/dtm.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE("dtm") + +static DECLARE_HASHTABLE(registry, 32); +static struct device_cat* dt_category; + +struct figura +{ + char val; + bool optional; +}; + +#define hash(def) ((unsigned int)__ptr(def)) + +static struct dtm_driver_record* +__locate_record(struct device_def* def) +{ + struct dtm_driver_record *p, *n; + + hashtable_hash_foreach(registry, hash(def), p, n, node) + { + if (p->def == def) { + return p; + } + } + + return NULL; +} + + +static inline void +__get_patternlet(const char* str, unsigned i, size_t len, + struct figura* fig) +{ + fig->optional = (i + 1 < len && str[i + 1] == '?'); + + if (i >= len) { + fig->val = 0; + return; + } + + fig->val = str[i]; +} + +/** + * A simplified regular expression matcher: + * 1. '*' matches any substring including empty string + * 2. '?' mark the prefixed character optional (an epsilon transition) + */ +static bool +__try_match(const char* str, const char* pattern, size_t pat_sz) +{ + unsigned j = 0, i = 0; + int saved_star = -1, saved_pos = 0; + size_t str_sz = strlen(str); + + char c; + struct figura p0, p1; + + while (i < str_sz) { + c = str[i++]; + __get_patternlet(pattern, j, pat_sz, &p0); + __get_patternlet(pattern, j + 1, pat_sz, &p1); + + if (p0.val == c) { + j += 1 + !!p0.optional; + saved_pos = (int)i; + continue; + } + + if (p0.val == '*') { + saved_pos = i; + saved_star = (int)j; + + if (p1.optional || p1.val == c) { + ++j; --i; + } + + continue; + } + + if (p0.optional) { + --i; j += 2; + continue; + } + + if (saved_star < 0) { + return false; + } + + j = (unsigned)saved_star; + i = (unsigned)saved_pos; + } + + return j + 1 >= pat_sz; +} + +static struct device_meta* +__try_create_categorical(struct dt_node_base *p) +{ + if (!p) return NULL; + + struct device_meta* parent = NULL; + struct device_cat* cat; + + parent = __try_create_categorical(p->parent); + parent = parent ?: dev_meta(dt_category); + + if (!p->compat.size) { + return parent; + } + + if (p->binded_dev) { + cat = changeling_reveal(p->binded_dev, devcat_morpher); + } + else { + cat = device_addcat(parent, HSTR_VAL(dt_mobj(p)->name)); + p->binded_dev = dev_mobj(cat); + } + + return dev_meta(cat); +} + +static bool +compat_matched(struct dtm_driver_record* rec, struct dt_node_base *base) +{ + const char *compat; + struct dtm_driver_info *p, *n; + + list_for_each(p, n, rec->infos.first, node) + { + size_t pat_len = strlen(p->pattern); + dtprop_strlst_foreach(compat, &base->compat) + { + if (__try_match(compat, p->pattern, pat_len)) { + return true; + } + } + } + + return false; +} + +static int +dtm_try_create_from(struct device_def* def) +{ + int err; + const char *name; + struct dt_context* dtctx; + struct dtm_driver_record* rec; + struct dt_node_base *p, *n; + + dtctx = dt_main_context(); + + rec = __locate_record(def); + if (!rec) { + return ENOENT; + } + + llist_for_each(p, n, &dtctx->nodes, nodes) + { + if (!p->compat.size) { + continue; + } + + if (!compat_matched(rec, p)) { + continue; + } + + __try_create_categorical(p); + + if ((err = def->create(def, dt_mobj(p)))) { + name = HSTR_VAL(dt_mobj(p)->name); + WARN("failed to bind devtree node %s, err=%d", name, err); + } + } + + return 0; +} + +void +dtm_register_entry(struct device_def* def, const char* pattern) +{ + struct dtm_driver_info* info; + struct dtm_driver_record* record; + + info = valloc(sizeof(*info)); + info->pattern = pattern; + + record = __locate_record(def); + if (!record) { + record = valloc(sizeof(*record)); + record->def = def; + list_head_init(&record->infos); + + hashtable_hash_in(registry, &record->node, hash(def)); + } + + list_add(&record->infos, &info->node); + + device_chain_loader(def, dtm_try_create_from); +} + +static void +dtm_init() +{ + hashtable_init(registry); + + dt_category = device_addcat(NULL, "tree"); +} +owloysius_fetch_init(dtm_init, on_sysconf); \ No newline at end of file diff --git a/lunaix-os/hal/gfxa/gfxm.c b/lunaix-os/hal/gfxa/gfxm.c index 27d1531..a58e88c 100644 --- a/lunaix-os/hal/gfxa/gfxm.c +++ b/lunaix-os/hal/gfxa/gfxm.c @@ -13,7 +13,7 @@ DECLARE_HASHTABLE(gfxa_idset, 8); struct device_cat* gfxa_devcat = NULL; static int id = 0; -static struct devclass gfxa_class = DEVCLASS(DEV_BUILTIN, DEVFN_DISP, DEV_GFXA); +static struct devclass gfxa_class = DEVCLASS(GENERIC, DISP, GFXA); static int __gfxa_cmd_router(struct device* dev, u32_t req, va_list args) diff --git a/lunaix-os/hal/gfxa/vga/vga_pci.c b/lunaix-os/hal/gfxa/vga/vga_pci.c index 1109e5a..af4f228 100644 --- a/lunaix-os/hal/gfxa/vga/vga_pci.c +++ b/lunaix-os/hal/gfxa/vga/vga_pci.c @@ -58,22 +58,26 @@ static u32_t palette[] = { #define VGA_REG_OFF 0x0400 static int -vga_pci_bind(struct device_def* devdef, struct device* pcidev_base) +vga_pci_bind(struct device_def* devdef, morph_t* obj) { - struct pci_device* pcidev = PCI_DEVICE(pcidev_base); + struct pci_probe* probe; - struct pci_base_addr* fb = &pcidev->bar[0]; - struct pci_base_addr* mmio = &pcidev->bar[2]; + struct pci_base_addr* fb; + struct pci_base_addr* mmio; + + probe = changeling_reveal(obj, pci_probe_morpher); + fb = &probe->bar[0]; + mmio = &probe->bar[2]; if (PCI_BAR_ADDR_IO(mmio->type)) { return EINVAL; } - pci_reg_t cmd = pci_read_cspace(pcidev->cspace_base, PCI_REG_STATUS_CMD); + pci_reg_t cmd = pci_read_cspace(probe->cspace_base, PCI_REG_STATUS_CMD); cmd |= (PCI_RCMD_MM_ACCESS | PCI_RCMD_DISABLE_INTR | PCI_RCMD_BUS_MASTER); - pci_write_cspace(pcidev->cspace_base, PCI_REG_STATUS_CMD, cmd); + pci_write_cspace(probe->cspace_base, PCI_REG_STATUS_CMD, cmd); ptr_t fb_mapped = ioremap(fb->start, FB256K); ptr_t mmio_mapped = ioremap(mmio->start, mmio->size); @@ -96,27 +100,27 @@ vga_pci_bind(struct device_def* devdef, struct device* pcidev_base) return 0; } -static int -vga_pci_init(struct device_def* def) -{ - return pci_bind_definition_all(pcidev_def(def)); -} +static bool +vga_pci_compat(struct pci_probe* probe) +{ #define VGA_PCI_CLASS 0x30000 + return pci_device_class(probe) == VGA_PCI_CLASS; +} -static bool -vga_pci_compat(struct pci_device_def* def, - struct pci_device* pcidev) +static int +vga_pci_register(struct device_def* def) { - return pci_device_class(pcidev) == VGA_PCI_CLASS; + return !pci_register_driver(def, vga_pci_compat); } +static struct device_def vga_pci_devdef = { + def_device_class(GENERIC, DISP, VGA), + def_device_name("Generic VGA"), + + def_on_register(vga_pci_register), + def_on_create(vga_pci_bind), -static struct pci_device_def vga_pci_devdef = { - .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_DISP, DEV_VGA), - .name = "Generic VGA", - .init = vga_pci_init, - .bind = vga_pci_bind }, - .test_compatibility = vga_pci_compat + def_non_trivial }; -EXPORT_PCI_DEVICE(vga_pci, &vga_pci_devdef, load_onboot); \ No newline at end of file +EXPORT_DEVICE(vga_pci, &vga_pci_devdef, load_onboot); \ No newline at end of file diff --git a/lunaix-os/hal/rtc/rtc_device.c b/lunaix-os/hal/rtc/rtc_device.c index ad06343..396c9bb 100644 --- a/lunaix-os/hal/rtc/rtc_device.c +++ b/lunaix-os/hal/rtc/rtc_device.c @@ -2,34 +2,51 @@ #include #include #include +#include #include -const struct hwrtc* sysrtc; -static int rtc_count = 0; +const struct hwrtc_potens* sysrtc = NULL; -DEFINE_LLIST(rtcs); +static DEFINE_LLIST(rtcs); + +LOG_MODULE("hwrtc") void hwrtc_walltime(datetime_t* dt) { - sysrtc->get_walltime(sysrtc, dt); + sysrtc->ops->get_walltime(sysrtc, dt); +} + +static inline struct hwrtc_potens* +__rtc_potens(struct device* wrapper) +{ + struct potens_meta* pot; + pot = device_get_potens(wrapper, potens(HWRTC)); + return ({ assert(pot); get_potens(pot, struct hwrtc_potens); }); } static int -hwrtc_ioctl(struct device* dev, u32_t req, va_list args) +__hwrtc_ioctl(struct device* dev, u32_t req, va_list args) { - struct hwrtc* rtc = (struct hwrtc*)dev->underlay; + struct hwrtc_potens* pot; + struct hwrtc_potens_ops* ops; + struct device* rtcdev; + + rtcdev = (struct device*) dev->underlay; + pot = __rtc_potens(rtcdev); + ops = pot->ops; + switch (req) { case RTCIO_IMSK: - rtc->set_mask(rtc); + ops->set_proactive(pot, false); break; case RTCIO_IUNMSK: - rtc->cls_mask(rtc); + ops->set_proactive(pot, true); break; case RTCIO_SETDT: datetime_t* dt = va_arg(args, datetime_t*); - rtc->set_walltime(rtc, dt); + ops->set_walltime(pot, dt); break; case RTCIO_SETFREQ: ticks_t* freq = va_arg(args, ticks_t*); @@ -38,75 +55,105 @@ hwrtc_ioctl(struct device* dev, u32_t req, va_list args) return EINVAL; } if (*freq) { - return rtc->chfreq(rtc, *freq); + return ops->chfreq(pot, *freq); } - *freq = rtc->base_freq; + *freq = pot->base_freq; break; default: - return EINVAL; + return rtcdev->ops.exec_cmd(dev, req, args); } return 0; } static int -hwrtc_read(struct device* dev, void* buf, size_t offset, size_t len) +__hwrtc_read(struct device* dev, void* buf, size_t offset, size_t len) { - struct hwrtc* rtc = (struct hwrtc*)dev->underlay; - *((ticks_t*)buf) = rtc->get_counts(rtc); + struct hwrtc_potens* pot; + + pot = __rtc_potens((struct device*)dev->underlay); + *((ticks_t*)buf) = pot->live; return sizeof(ticks_t); } -struct hwrtc* -hwrtc_alloc_new(char* name) +static struct devclass proxy_rtc_clas = DEVCLASS(LUNAIX, TIME, RTC); + +static void +__hwrtc_create_proxy(struct hwrtc_potens* pot, struct device* raw_rtcdev) { - struct hwrtc* rtc_instance = valloc(sizeof(struct hwrtc)); + struct device* dev; - if (!rtc_instance) { - return NULL; - } + dev = device_allocsys(NULL, raw_rtcdev); + + dev->ops.exec_cmd = __hwrtc_ioctl; + dev->ops.read = __hwrtc_read; - llist_append(&rtcs, &rtc_instance->rtc_list); + register_device_var(dev, &proxy_rtc_clas, "rtc"); - rtc_instance->id = rtc_count++; - rtc_instance->name = name; - struct device* rtcdev = device_allocsys(NULL, rtc_instance); + pot->rtc_proxy = dev; +} + +struct hwrtc_potens* +hwrtc_attach_potens(struct device* raw_rtcdev, struct hwrtc_potens_ops* ops) +{ + struct hwrtc_potens* hwpot; + + if (!potens_check_unique(raw_rtcdev, potens(HWRTC))) + { + return NULL; + } - rtcdev->ops.exec_cmd = hwrtc_ioctl; - rtcdev->ops.read = hwrtc_read; + hwpot = new_potens(potens(HWRTC), struct hwrtc_potens); + hwpot->ops = ops; + + device_grant_potens(raw_rtcdev, potens_meta(hwpot)); + llist_append(&rtcs, &hwpot->rtc_potentes); - rtc_instance->rtc_dev = rtcdev; + __hwrtc_create_proxy(hwpot, raw_rtcdev); - return rtc_instance; + return hwpot; } void -hwrtc_register(struct devclass* class, struct hwrtc* rtc) +hwrtc_init() { - if (unlikely(!sysrtc)) { - sysrtc = rtc; + assert(!llist_empty(&rtcs)); + + sysrtc = list_entry(rtcs.next, struct hwrtc_potens, rtc_potentes); + + if (!sysrtc->ops->calibrate) { + return; } - class->variant = rtc->id; - register_device(rtc->rtc_dev, class, "rtc%d", rtc->id); + int err = sysrtc->ops->calibrate(sysrtc); + if (err) { + FATAL("failed to calibrate rtc. name='%s', err=%d", + potens_dev(sysrtc)->name_val, err); + } } static void __hwrtc_readinfo(struct twimap* mapping) { - struct hwrtc* rtc = twimap_data(mapping, struct hwrtc*); - twimap_printf(mapping, "name: %s\n", rtc->name); - twimap_printf(mapping, "frequency: %dHz\n", rtc->base_freq); - twimap_printf(mapping, "ticks count: %d\n", rtc->get_counts(rtc)); - twimap_printf(mapping, - "ticking: %s\n", - (rtc->state & RTC_STATE_MASKED) ? "no" : "yes"); + struct hwrtc_potens* pot; + struct device* owner; + + pot = twimap_data(mapping, struct hwrtc_potens*); + owner = pot->pot_meta.owner; + + twimap_printf(mapping, "device: %x.%x\n", + owner->ident.fn_grp, owner->ident.unique); + + twimap_printf(mapping, "frequency: %dHz\n", pot->base_freq); + twimap_printf(mapping, "ticks count: %d\n", pot->live); + twimap_printf(mapping, "ticking: %s\n", + (pot->state & RTC_STATE_MASKED) ? "no" : "yes"); datetime_t dt; - rtc->get_walltime(rtc, &dt); + pot->ops->get_walltime(pot, &dt); twimap_printf( mapping, "recorded date: %d/%d/%d\n", dt.year, dt.month, dt.day); @@ -116,18 +163,18 @@ __hwrtc_readinfo(struct twimap* mapping) } static void -hwrtc_twifs_export(struct hwrtc* rtc) +hwrtc_twifs_export(struct hwrtc_potens* pot) { - const char* name = rtc->rtc_dev->name.value; - struct twimap* rtc_mapping = twifs_mapping(NULL, rtc, name); + const char* name = pot->rtc_proxy->name_val; + struct twimap* rtc_mapping = twifs_mapping(NULL, pot, name); rtc_mapping->read = __hwrtc_readinfo; } static void hwrtc_twifs_export_all() { - struct hwrtc *pos, *next; - llist_for_each(pos, next, &rtcs, rtc_list) + struct hwrtc_potens *pos, *next; + llist_for_each(pos, next, &rtcs, rtc_potentes) { hwrtc_twifs_export(pos); } diff --git a/lunaix-os/hal/term/console.c b/lunaix-os/hal/term/console.c index 1c2a2cf..ea479a3 100644 --- a/lunaix-os/hal/term/console.c +++ b/lunaix-os/hal/term/console.c @@ -35,7 +35,7 @@ setup_default_tty() assert(device_addalias(NULL, dev_meta(dev), "tty")); - if (!device_get_capability(dev, TERMIOS_CAP)) { + if (!device_get_potens(dev, potens(TERMPORT))) { FATAL("not a terminal device: %s", console_dev); } diff --git a/lunaix-os/hal/term/default_ops.c b/lunaix-os/hal/term/default_ops.c index fea8355..ca0aa2c 100644 --- a/lunaix-os/hal/term/default_ops.c +++ b/lunaix-os/hal/term/default_ops.c @@ -18,7 +18,7 @@ __tpcap_default_set_cntrl_mode(struct device* dev, tcflag_t cflag) } -struct termport_cap_ops default_termport_cap_ops = { +struct termport_pot_ops default_termport_pot_ops = { .set_cntrl_mode = __tpcap_default_set_cntrl_mode, .set_clkbase = __tpcap_default_set_baseclk, .set_speed = __tpcap_default_set_speed diff --git a/lunaix-os/hal/term/term.c b/lunaix-os/hal/term/term.c index 4353265..a71f93c 100644 --- a/lunaix-os/hal/term/term.c +++ b/lunaix-os/hal/term/term.c @@ -5,17 +5,22 @@ #include #include #include +#include #include +LOG_MODULE("term"); + #define termdev(dev) ((struct term*)(dev)->underlay) #define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*)) -static struct devclass termdev_class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM); +static struct devclass termdev_class = DEVCLASS(LUNAIX, TTY, VTERM); struct device* sysconsole = NULL; +extern struct termport_pot_ops default_termport_pot_ops; + static int term_exec_cmd(struct device* dev, u32_t req, va_list args) { @@ -81,7 +86,7 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args) tios->c_baud = term->iospeed; } break; case TDEV_TCSETATTR: { - struct termport_cap_ops* cap_ops; + struct termport_pot_ops* pot_ops; struct termios* tios = va_arg(args, struct termios*); term->iflags = tios->c_iflag; @@ -96,16 +101,16 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args) goto done; } - cap_ops = term->tp_cap->cap_ops; + pot_ops = term->tp_cap->ops; if (tios->c_baud != term->iospeed) { term->iospeed = tios->c_baud; - cap_ops->set_speed(term->chdev, tios->c_baud); + pot_ops->set_speed(term->chdev, tios->c_baud); } if (old_cf != tios->c_cflag) { - cap_ops->set_cntrl_mode(term->chdev, tios->c_cflag); + pot_ops->set_cntrl_mode(term->chdev, tios->c_cflag); } } break; default: @@ -177,13 +182,13 @@ alloc_term_buffer(struct term* terminal, size_t sz_hlf) terminal->scratch_pad = valloc(sz_hlf); } -struct term* -term_create(struct device* chardev, char* suffix) +struct termport_potens* +term_attach_potens(struct device* chardev, + struct termport_pot_ops* ops, char* suffix) { struct term* terminal; struct device* tdev; - struct capability_meta* termport_cap; - struct capability_meta* tios_cap; + struct termport_potens* tp_cap; terminal = vzalloc(sizeof(struct term)); if (!terminal) { @@ -206,24 +211,22 @@ term_create(struct device* chardev, char* suffix) int cdev_var = DEV_VAR_FROM(chardev->ident.unique); register_device(tdev, &termdev_class, "tty%s%d", suffix, cdev_var); } else { - register_device(tdev, &termdev_class, "tty%d", termdev_class.variant++); + register_device_var(tdev, &termdev_class, "tty"); } - termport_cap = device_get_capability(chardev, TERMPORT_CAP); - if (termport_cap) { - terminal->tp_cap = - get_capability(termport_cap, struct termport_capability); - - assert(terminal->tp_cap->cap_ops); - terminal->tp_cap->term = terminal; - } + INFO("spawned: %s", tdev->name_val); + + tp_cap = new_potens(potens(TERMPORT), struct termport_potens); + tp_cap->ops = ops ?: &default_termport_pot_ops; + + terminal->tp_cap = tp_cap; + tp_cap->term = terminal; - tios_cap = new_capability_marker(TERMIOS_CAP); - device_grant_capability(tdev, tios_cap); + device_grant_potens(tdev, potens_meta(tp_cap)); load_default_setting(terminal); - return terminal; + return tp_cap; } int diff --git a/lunaix-os/hal/term/term_io.c b/lunaix-os/hal/term/term_io.c index 2c0fb66..03a9572 100644 --- a/lunaix-os/hal/term/term_io.c +++ b/lunaix-os/hal/term/term_io.c @@ -99,7 +99,7 @@ term_flush(struct term* tdev) } void -term_notify_data_avaliable(struct termport_capability* cap) +term_notify_data_avaliable(struct termport_potens* cap) { struct term* term; struct device* term_chrdev; diff --git a/lunaix-os/hal/timer/timer_device.c b/lunaix-os/hal/timer/timer_device.c index 1db8147..085f6bd 100644 --- a/lunaix-os/hal/timer/timer_device.c +++ b/lunaix-os/hal/timer/timer_device.c @@ -3,26 +3,23 @@ #include -const struct hwtimer* systimer; +const struct hwtimer_pot* systimer = NULL; -ticks_t -hwtimer_base_frequency() -{ - assert(systimer); - return systimer->base_freq; -} +static struct device_alias* timer_alias; +static DEFINE_LLIST(timer_devices); ticks_t hwtimer_current_systicks() { assert(systimer); - return systimer->systicks(); + return systimer->systick_raw; } ticks_t hwtimer_to_ticks(u32_t value, int unit) { assert(systimer); + // in case system frequency is less than 1000Hz if (unit != TIME_MS) { return systimer->running_freq * unit * value; @@ -33,34 +30,66 @@ hwtimer_to_ticks(u32_t value, int unit) return freq_ms * value; } -static int -__hwtimer_ioctl(struct device* dev, u32_t req, va_list args) +static struct hwtimer_pot* +__select_timer() { - struct hwtimer* hwt = (struct hwtimer*)dev->underlay; - switch (req) { - case TIMERIO_GETINFO: - // TODO - break; - - default: - break; + struct hwtimer_pot *pos, *n, *sel = NULL; + + llist_for_each(pos, n, &timer_devices, timers) + { + if (unlikely(!sel)) { + sel = pos; + continue; + } + + if (sel->precedence < pos->precedence) { + sel = pos; + } } - return 0; + + return sel; } void hwtimer_init(u32_t hertz, void* tick_callback) { - struct hwtimer* hwt_ctx = select_platform_timer(); + struct hwtimer_pot* selected; + struct device* time_dev; + + selected = __select_timer(); - hwt_ctx->init(hwt_ctx, hertz, tick_callback); - hwt_ctx->running_freq = hertz; + assert(selected); + systimer = selected; - systimer = hwt_ctx; + selected->callback = tick_callback; + selected->running_freq = hertz; + + selected->ops->calibrate(selected, hertz); + + time_dev = potens_dev(selected); + timer_alias = device_addalias(NULL, dev_meta(time_dev), "timer"); +} + + +struct hwtimer_pot* +hwtimer_attach_potens(struct device* dev, int precedence, + struct hwtimer_pot_ops* ops) +{ + struct hwtimer_pot* hwpot; + struct potens_meta* pot; + + if (!potens_check_unique(dev, potens(HWTIMER))) + { + return NULL; + } - struct device* timerdev = device_allocsys(NULL, hwt_ctx); + hwpot = new_potens(potens(HWTIMER), struct hwtimer_pot); + hwpot->ops = ops; + hwpot->precedence = precedence; + + device_grant_potens(dev, potens_meta(hwpot)); - timerdev->ops.exec_cmd = __hwtimer_ioctl; + llist_append(&timer_devices, &hwpot->timers); - register_device(timerdev, &hwt_ctx->class, hwt_ctx->name); + return hwpot; } \ No newline at end of file diff --git a/lunaix-os/includes/hal/devtree.h b/lunaix-os/includes/hal/devtree.h index 088e66f..7b02ca5 100644 --- a/lunaix-os/includes/hal/devtree.h +++ b/lunaix-os/includes/hal/devtree.h @@ -6,6 +6,9 @@ #include #include #include +#include + +#include #define le(v) ((((v) >> 24) & 0x000000ff) |\ (((v) << 8) & 0x00ff0000) |\ @@ -34,7 +37,10 @@ typedef unsigned int* dt_enc_t; typedef unsigned int dt_phnd_t; -typedef bool (*node_predicate_t)(struct dt_node_iter*, struct dt_node*); + +struct dt_node_base; +struct dt_node_iter; +typedef bool (*node_predicate_t)(struct dt_node_iter*, struct dt_node_base*); #define PHND_NULL ((dt_phnd_t)-1) @@ -83,7 +89,7 @@ struct dt_prop_val { union { const char* str_val; - const char** str_lst; + const char* str_lst; }; ptr_t ptr_val; @@ -107,8 +113,18 @@ struct dt_prop struct dt_prop_val val; }; +struct dt_prop_table +{ + union { + struct hbucket other_props[0]; + struct hbucket _op_bucket[8]; + }; +}; + struct dt_node_base { + morph_t mobj; + union { struct { unsigned char addr_c; @@ -130,23 +146,15 @@ struct dt_node_base }; struct dt_node_base *parent; - struct llist_header children; - struct llist_header siblings; struct llist_header nodes; - struct hlist_node phnd_link; - - const char* name; struct dt_prop_val compat; - const char* model; dt_phnd_t phandle; - union { - struct hbucket other_props[0]; - struct hbucket _op_bucket[8]; - }; + struct dt_prop_table* props; void* obj; + morph_t* binded_dev; }; struct dt_root @@ -212,7 +220,11 @@ struct dt_intr_node struct dt_node { - struct dt_node_base base; + union { + morph_t mobj; + struct dt_node_base base; + }; + struct dt_intr_node intr; struct dt_prop_val reg; @@ -221,7 +233,9 @@ struct dt_node struct dt_prop_val ranges; struct dt_prop_val dma_ranges; }; - +#define dt_parent(node) ((node)->base.parent) +#define dt_morpher morphable_attrs(dt_node, mobj) +#define dt_mobj(node) (&(node)->mobj) struct dt_intr_prop { @@ -378,6 +392,9 @@ dt_found_any(struct dt_node_iter* iter) return !!iter->matched; } +struct dt_context* +dt_main_context(); + /**** * DT Main Functions: Node-binding @@ -437,6 +454,11 @@ dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node, #define dtprop_extract(dtpi, off) \ ( (dt_enc_t) (&(dtpi)->prop_loc[(off)]) ) +#define dtprop_strlst_foreach(pos, prop) \ + for (pos = (prop)->str_lst; \ + pos <= &(prop)->str_lst[(prop)->size]; \ + pos = &pos[strlen(pos) + 1]) + static inline bool dtprop_next_n(struct dt_prop_iter* dtpi, int n) { diff --git a/lunaix-os/includes/hal/devtreem.h b/lunaix-os/includes/hal/devtreem.h new file mode 100644 index 0000000..c8d10c2 --- /dev/null +++ b/lunaix-os/includes/hal/devtreem.h @@ -0,0 +1,48 @@ +#ifndef __LUNAIX_DEVTREE_TOP_H +#define __LUNAIX_DEVTREE_TOP_H + +struct device_def; +struct device; + +#ifdef CONFIG_USE_DEVICETREE + +#include "devtree.h" +#include +#include +#include + +typedef struct dt_node* devtree_link_t; + +#define dt_node_morpher morphable_attrs(dt_node, mobj) + +struct dtm_driver_info +{ + struct list_node node; + const char* pattern; +}; + +struct dtm_driver_record +{ + struct hlist_node node; + struct list_head infos; + struct device_def* def; +}; + +void +dtm_register_entry(struct device_def* def, const char* pattern); + +#else + +#include + +typedef void* devtree_link_t; + +static inline void +dtm_register_entry(struct device_def* def, const char* pattern) +{ + return; +} + +#endif + +#endif /* __LUNAIX_DEVTREE_TOP_H */ diff --git a/lunaix-os/includes/hal/hwrtc.h b/lunaix-os/includes/hal/hwrtc.h index c0186ff..37a1877 100644 --- a/lunaix-os/includes/hal/hwrtc.h +++ b/lunaix-os/includes/hal/hwrtc.h @@ -8,35 +8,38 @@ #define RTC_STATE_MASKED 0x1 -#define EXPORT_RTC_DEVICE(id, init_fn) \ - export_ldga_el(rtcdev, id, ptr_t, init_fn) +struct hwrtc_potens; +struct hwrtc_potens_ops +{ + void (*get_walltime)(struct hwrtc_potens*, datetime_t*); + void (*set_walltime)(struct hwrtc_potens*, datetime_t*); + void (*set_proactive)(struct hwrtc_potens*, bool); + int (*chfreq)(struct hwrtc_potens*, int); + + int (*calibrate)(struct hwrtc_potens*); +}; -struct hwrtc +struct hwrtc_potens { - struct llist_header rtc_list; - struct device* rtc_dev; + POTENS_META; + + struct llist_header rtc_potentes; + struct device* rtc_proxy; - int id; - char* name; - void* data; ticks_t base_freq; + volatile ticks_t live; int state; - void (*get_walltime)(struct hwrtc*, datetime_t*); - void (*set_walltime)(struct hwrtc*, datetime_t*); - void (*set_mask)(struct hwrtc*); - void (*cls_mask)(struct hwrtc*); - int (*get_counts)(struct hwrtc*); - int (*chfreq)(struct hwrtc*, int); + struct hwrtc_potens_ops* ops; }; -struct hwrtc* -hwrtc_alloc_new(char* name); +void +hwrtc_init(); void hwrtc_walltime(datetime_t* dt); -void -hwrtc_register(struct devclass* class, struct hwrtc* rtc); +struct hwrtc_potens* +hwrtc_attach_potens(struct device* raw_rtcdev, struct hwrtc_potens_ops* ops); #endif /* __LUNAIX_HWRTC_H */ diff --git a/lunaix-os/includes/hal/hwtimer.h b/lunaix-os/includes/hal/hwtimer.h index 2faa507..e7a22a7 100644 --- a/lunaix-os/includes/hal/hwtimer.h +++ b/lunaix-os/includes/hal/hwtimer.h @@ -7,34 +7,42 @@ typedef void (*timer_tick_cb)(); -struct hwtimer -{ - char* name; - void* data; +#define HWTIMER_MIN_PRECEDENCE 0 +#define HWTIMER_MAX_PRECEDENCE 15 - struct devclass class; - struct device* timer_dev; +struct hwtimer_pot; +struct hwtimer_pot_ops +{ + void (*calibrate)(struct hwtimer_pot*, u32_t hertz); +}; - int (*supported)(struct hwtimer*); - void (*init)(struct hwtimer*, u32_t hertz, timer_tick_cb); - ticks_t (*systicks)(); +struct hwtimer_pot +{ + POTENS_META; + + struct llist_header timers; + + int precedence; + timer_tick_cb callback; ticks_t base_freq; ticks_t running_freq; + volatile ticks_t systick_raw; + + struct hwtimer_pot_ops* ops; }; void hwtimer_init(u32_t hertz, void* tick_callback); -struct hwtimer* -select_platform_timer(); - -ticks_t -hwtimer_base_frequency(); - ticks_t hwtimer_current_systicks(); ticks_t hwtimer_to_ticks(u32_t value, int unit); +struct hwtimer_pot* +hwtimer_attach_potens(struct device* dev, int precedence, + struct hwtimer_pot_ops* ops); + + #endif /* __LUNAIX_HWTIMER_H */ diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h index 95ed7fd..37815fe 100644 --- a/lunaix-os/includes/hal/pci.h +++ b/lunaix-os/includes/hal/pci.h @@ -4,21 +4,12 @@ #include #include #include +#include #include +#include #include -#define EXPORT_PCI_DEVICE(id, pci_devdef, stage) \ - EXPORT_DEVICE(id, &(pci_devdef)->devdef, stage) - -#define PCI_MATCH_EXACT -1 -#define PCI_MATCH_ANY 0 -#define PCI_MATCH_VENDOR 0xffff - -#define PCI_TDEV 0x0 -#define PCI_TPCIBRIDGE 0x1 -#define PCI_TCARDBRIDGE 0x2 - #define PCI_VENDOR_INVLD 0xffff #define PCI_REG_VENDOR_DEV 0 @@ -65,8 +56,6 @@ #define PCILOC_DEV(loc) (((loc) >> 3) & 0x1f) #define PCILOC_FN(loc) ((loc) & 0x7) -#define PCI_ID_ANY (-1) - typedef unsigned int pci_reg_t; typedef u16_t pciaddr_t; @@ -84,17 +73,9 @@ struct pci_base_addr u32_t type; }; -struct pci_device +struct pci_probe { - struct device dev; - struct llist_header dev_chain; - struct hlist_node dev_cache; - - struct - { - struct device* dev; - struct device_def* def; - } binding; + morph_t mobj; pciaddr_t loc; u16_t intr_info; @@ -103,48 +84,23 @@ struct pci_device u32_t cspace_base; u32_t msi_loc; struct pci_base_addr bar[6]; -}; -#define PCI_DEVICE(devbase) (container_of((devbase), struct pci_device, dev)) -struct pci_device_list -{ - struct llist_header peers; - struct pci_device* pcidev; + struct device* bind; }; +#define pci_probe_morpher morphable_attrs(pci_probe, mobj) -typedef void* (*pci_drv_init)(struct pci_device*); +typedef bool (*pci_id_checker_t)(struct pci_probe*); -#define PCI_DEVIDENT(vendor, id) \ - ((((id) & 0xffff) << 16) | (((vendor) & 0xffff))) - -struct pci_device_def +struct pci_registry { - struct device_def devdef; + struct hlist_node entries; + struct device_def* definition; - bool (*test_compatibility)(struct pci_device_def*, struct pci_device*); + pci_id_checker_t check_compact; }; -#define pcidev_def(dev_def_ptr) \ - container_of((dev_def_ptr), struct pci_device_def, devdef) -#define binded_pcidev(pcidev) ((pcidev)->binding.def) - -/** - * @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备 - * 类型代码请参阅: PCI LB Spec. Appendix D. - * - * @return struct pci_device* - */ -struct pci_device* pci_get_device_by_class(u32_t class); - -/** - * @brief 根据设备商ID和设备ID,在拓扑中寻找一个设备 - * - * @param vendorId - * @param deviceId - * @return struct pci_device* - */ -struct pci_device* -pci_get_device_by_id(u16_t vendorId, u16_t deviceId); +bool +pci_register_driver(struct device_def* def, pci_id_checker_t checker); /** * @brief 初始化PCI设备的基地址寄存器。返回由该基地址代表的, @@ -157,54 +113,73 @@ pci_get_device_by_id(u16_t vendorId, u16_t deviceId); * @return size_t */ size_t -pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num); +pci_bar_sizing(struct pci_probe* probe, u32_t* bar_out, u32_t bar_num); /** * @brief Bind an abstract device instance to the pci device * * @param pcidev pci device - * @param devobj abstract device instance + * @param dev abstract device instance */ -void -pci_bind_instance(struct pci_device* pcidev, void* devobj); +static inline void +pci_bind_instance(struct pci_probe* probe, struct device* dev) +{ + probe->bind = dev; -void -pci_probe_bar_info(struct pci_device* device); +} -void -pci_setup_msi(struct pci_device* device, msi_vector_t msiv); +msienv_t +pci_msi_start(struct pci_probe* probe); -void -pci_probe_msi_info(struct pci_device* device); +msi_vector_t +pci_msi_setup_at(msienv_t msienv, struct pci_probe* probe, + int i, isr_cb handler); -int -pci_bind_definition(struct pci_device_def* pcidev_def, bool* more); +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_definition_all(struct pci_device_def* pcidef); +pci_bind_driver(struct pci_registry* reg); + static inline unsigned int -pci_device_vendor(struct pci_device* pcidev) +pci_device_vendor(struct pci_probe* probe) { - return PCI_DEV_VENDOR(pcidev->device_info); + return PCI_DEV_VENDOR(probe->device_info); } static inline unsigned int -pci_device_devid(struct pci_device* pcidev) +pci_device_devid(struct pci_probe* probe) { - return PCI_DEV_DEVID(pcidev->device_info); + return PCI_DEV_DEVID(probe->device_info); } static inline unsigned int -pci_device_class(struct pci_device* pcidev) +pci_device_class(struct pci_probe* probe) { - return PCI_DEV_CLASS(pcidev->class_info); + return PCI_DEV_CLASS(probe->class_info); } static inline struct pci_base_addr* -pci_device_bar(struct pci_device* pcidev, int index) +pci_device_bar(struct pci_probe* probe, int index) { - return &pcidev->bar[index]; + return &probe->bar[index]; } static inline void @@ -213,6 +188,11 @@ pci_cmd_set_mmio(pci_reg_t* cmd) *cmd |= PCI_RCMD_MM_ACCESS; } +static inline ptr_t +pci_requester_id(struct pci_probe* probe) +{ + return probe->loc; +} static inline void pci_cmd_set_pmio(pci_reg_t* cmd) @@ -245,19 +225,19 @@ pci_bar_mmio_space(struct pci_base_addr* bar) } static inline bool -pci_capability_msi(struct pci_device* pcidev) +pci_capability_msi(struct pci_probe* probe) { - return !!pcidev->msi_loc; + return !!probe->msi_loc; } static inline int -pci_intr_irq(struct pci_device* pcidev) +pci_intr_irq(struct pci_probe* probe) { - return PCI_INTR_IRQ(pcidev->intr_info); + return PCI_INTR_IRQ(probe->intr_info); } void -pci_apply_command(struct pci_device* pcidev, pci_reg_t cmd); +pci_apply_command(struct pci_probe* probe, pci_reg_t cmd); pci_reg_t pci_read_cspace(ptr_t base, int offset); diff --git a/lunaix-os/includes/hal/serial.h b/lunaix-os/includes/hal/serial.h index af345da..ba2185c 100644 --- a/lunaix-os/includes/hal/serial.h +++ b/lunaix-os/includes/hal/serial.h @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -33,7 +34,7 @@ struct serial_dev struct rbuffer rxbuf; int wr_len; - struct capability_meta* tp_cap; + struct termport_potens* tp_cap; /** * @brief Write buffer to TX. The return code indicate diff --git a/lunaix-os/includes/hal/term.h b/lunaix-os/includes/hal/term.h index 407707e..be7abd0 100644 --- a/lunaix-os/includes/hal/term.h +++ b/lunaix-os/includes/hal/term.h @@ -26,34 +26,19 @@ typedef struct rbuffer** lbuf_ref_t; #define ref_next(lbuf) (&(lbuf)->next) #define deref(bref) (*(bref)) -/** - * @brief Communication port capability that a device is supported natively, - * or able to emulate low level serial transmission behaviour specify - * by POSIX1-2008, section 11. - * - */ -#define TERMPORT_CAP 0x4d524554U - -/** - * @brief A termios capability that a device provide interfaces which is - * compliant to POSIX1-2008 - * - */ -#define TERMIOS_CAP 0x534f4954U - struct term; -struct termport_cap_ops +struct termport_pot_ops { void (*set_speed)(struct device*, speed_t); void (*set_clkbase)(struct device*, unsigned int); void (*set_cntrl_mode)(struct device*, tcflag_t); }; -struct termport_capability +struct termport_potens { - CAPABILITY_META; - struct termport_cap_ops* cap_ops; + POTENS_META; + struct termport_pot_ops* ops; struct term* term; }; @@ -66,7 +51,7 @@ struct term char* scratch_pad; pid_t fggrp; - struct termport_capability* tp_cap; + struct termport_potens* tp_cap; waitq_t line_in_event; /* -- POSIX.1-2008 compliant fields -- */ @@ -84,8 +69,9 @@ struct term extern struct device* sysconsole; -struct term* -term_create(struct device* chardev, char* suffix); +struct termport_potens* +term_attach_potens(struct device* chardev, + struct termport_pot_ops* ops, char* suffix); int term_bind(struct term* tdev, struct device* chdev); @@ -119,20 +105,7 @@ lcntl_transform_inseq(struct term* tdev); int lcntl_transform_outseq(struct term* tdev); -static inline void -term_cap_set_operations(struct termport_capability* cap, - struct termport_cap_ops* ops) -{ - cap->cap_ops = ops; -} - void -term_notify_data_avaliable(struct termport_capability* cap); - -#define termport_default_ops \ - ({ \ - extern struct termport_cap_ops default_termport_cap_ops;\ - &default_termport_cap_ops; \ - }) +term_notify_data_avaliable(struct termport_potens* cap); #endif /* __LUNAIX_TERM_H */ diff --git a/lunaix-os/includes/listings/changeling.lst b/lunaix-os/includes/listings/changeling.lst new file mode 100644 index 0000000..1e26576 --- /dev/null +++ b/lunaix-os/includes/listings/changeling.lst @@ -0,0 +1,7 @@ +morphable(dt_node), +morphable(pci_probe), + +morphable(device_meta), +morphable(device_cat), +morphable(device_alias), +morphable(device), \ No newline at end of file diff --git a/lunaix-os/includes/listings/device_potens.lst b/lunaix-os/includes/listings/device_potens.lst new file mode 100644 index 0000000..9534b9a --- /dev/null +++ b/lunaix-os/includes/listings/device_potens.lst @@ -0,0 +1,20 @@ +/** + * @brief Communication port capability that a device is supported natively, + * or able to emulate low level serial transmission behaviour specify + * by POSIX1-2008, section 11. + * + */ +potens(TERMPORT), + +/** + * @brief Hardware timer capability that allow such device to be integrated + and utilised by timer subsystem + * + */ +potens(HWTIMER), + +/** + * @brief RTC capability. + * + */ +potens(HWRTC), \ No newline at end of file diff --git a/lunaix-os/includes/listings/devnum.lst b/lunaix-os/includes/listings/devnum.lst new file mode 100644 index 0000000..81e5c1e --- /dev/null +++ b/lunaix-os/includes/listings/devnum.lst @@ -0,0 +1,20 @@ +dev_id(VTERM), +dev_id(RNG), + +dev_id(RTC), + +dev_id(SATA), +dev_id(NVME), +dev_id(PCI), +dev_id(UART16550), + +dev_id(TIMER), +dev_id(TIMER_APIC), +dev_id(TIMER_HEPT), + +dev_id(NIHIL), +dev_id(ZERO), +dev_id(KBD), +dev_id(GFXA), +dev_id(VGA), +dev_id(INTC), \ No newline at end of file diff --git a/lunaix-os/includes/listings/devnum_fn.lst b/lunaix-os/includes/listings/devnum_fn.lst new file mode 100644 index 0000000..ad02c87 --- /dev/null +++ b/lunaix-os/includes/listings/devnum_fn.lst @@ -0,0 +1,9 @@ +dev_fn(PSEUDO), +dev_fn(CHAR), +dev_fn(STORAGE), +dev_fn(INPUT), +dev_fn(TIME), +dev_fn(BUSIF), +dev_fn(TTY), +dev_fn(DISP), +dev_fn(CFG) \ No newline at end of file diff --git a/lunaix-os/includes/listings/devnum_vn.lst b/lunaix-os/includes/listings/devnum_vn.lst new file mode 100644 index 0000000..d898514 --- /dev/null +++ b/lunaix-os/includes/listings/devnum_vn.lst @@ -0,0 +1,3 @@ +dev_vn(LUNAIX), +dev_vn(INTEL), +dev_vn(ARM), \ No newline at end of file diff --git a/lunaix-os/includes/lunaix/changeling.h b/lunaix-os/includes/lunaix/changeling.h new file mode 100644 index 0000000..b9188ec --- /dev/null +++ b/lunaix-os/includes/lunaix/changeling.h @@ -0,0 +1,171 @@ +#ifndef __LUNAIX_CHANGELING_H +#define __LUNAIX_CHANGELING_H + +#include +#include +#include +#include + +#define CHLG_ID (unsigned short)0x4c43 + +#define morphable(struct_name) chlg_##struct_name +#define __morpher_id(struct_name, field) morphable(struct_name) +#define morpher_id(morpher) __morpher_id(morpher) + +enum changeling_idents +{ + morphable(anon) = 0, + #include +}; + +/** + * changeling - a proud changeling of her majesty :) + * changeling reginae superbum + */ +struct changeling +{ + struct { + union { + struct + { + unsigned short sig; + unsigned short ident; + }; + + unsigned int magic; + }; + }; + + int ref; + unsigned int uid; + + struct changeling *parent; + struct llist_header sibs; + struct llist_header subs; + struct hstr name; +}; + +typedef struct changeling morph_t; + +#define morphable_attrs(struct_name, field) struct_name, field +#define morphed_ptr(ptr_like) ((morph_t*)__ptr(ptr_like)) +#define morpher_uid(mobj) ((mobj)->uid) + +#define __changeling_morph(parent, chlg, name, struct_name, field) \ + ({ \ + changeling_init(parent, &(chlg), chlg_##struct_name, name); \ + &(chlg); \ + }) + +#define __morph_type_of(chlg, struct_name, field) \ + ((chlg)->ident == chlg_##struct_name) + +#define __changeling_cast(chlg, struct_name, field) \ + container_of(chlg, struct struct_name, field) + +#define __changeling_try_reveal(chlg, struct_name, field) \ + ({ \ + struct struct_name* __r = NULL; \ + if (__changeling_of(chlg, struct_name, field)) \ + __r = __changeling_cast(chlg, struct_name, field); \ + __r; \ + }) + +#define __changeling_reveal(chlg, struct_name, field) \ + ({ \ + struct struct_name* __r; \ + __r = __changeling_try_reveal(chlg, struct_name, field); \ + assert(__r); __r; \ + }) + +#define __changeling_of(chlg, struct_name, field) \ + (chlg && (chlg)->sig == CHLG_ID \ + && __morph_type_of(chlg, struct_name, field)) + + +#define changeling_morph(parent, chlg, name, morpher) \ + __changeling_morph(parent, chlg, name, morpher) + + +#define changeling_morph_anon(parent, chlg, morpher) \ + __changeling_morph(parent, chlg, NULL, morpher) + + +#define is_changeling(maybe_chlg) \ + ((maybe_chlg) && morphed_ptr(maybe_chlg)->sig == CHLG_ID) + + +#define morph_type_of(chlg, morpher) \ + __morph_type_of(chlg, morpher) + +#define changeling_of(chlg, morpher) \ + __changeling_of(chlg, morpher) + +#define changeling_try_reveal(chlg, morpher) \ + __changeling_try_reveal(chlg, morpher) + +#define changeling_reveal(chlg, morpher) \ + __changeling_reveal(chlg, morpher) + +#define changeling_for_each(pos, n, parent) \ + llist_for_each(pos, n, &(parent)->subs, sibs) + +static inline morph_t* +changeling_ref(morph_t* chlg) +{ + return ({ chlg->ref++; chlg; }); +} + +static inline morph_t* +changeling_unref(morph_t* chlg) +{ + assert(chlg->ref > 0); + return ({ chlg->ref--; chlg; }); +} + +static inline void +changeling_detach(morph_t* obj) +{ + if (llist_empty(&obj->sibs)) { + return; + } + + changeling_unref(obj); + llist_delete(&obj->sibs); +} + +static inline morph_t* +changeling_attach(morph_t* parent, morph_t* obj) +{ + changeling_detach(obj); + + llist_append(&parent->subs, &obj->sibs); + obj->parent = parent; + + return changeling_ref(obj); +} + +static inline void +changeling_isolate(morph_t* obj) +{ + changeling_detach(obj); + assert(obj->ref == 0); +} + +void +changeling_init(morph_t* parent, morph_t* chlg, + unsigned int id, const char* name); + +morph_t* +changeling_spawn(morph_t* parent, const char* name); + +morph_t* +changeling_find(morph_t* parent, struct hstr* str); + +morph_t* +changeling_get_at(morph_t* parent, int index); + +morph_t* +changeling_setname(morph_t* chlg, const char* name); + +#endif /* __LUNAIX_CHANGELING_H */ diff --git a/lunaix-os/includes/lunaix/clock.h b/lunaix-os/includes/lunaix/clock.h index 58e1ead..3cb1e4e 100644 --- a/lunaix-os/includes/lunaix/clock.h +++ b/lunaix-os/includes/lunaix/clock.h @@ -6,11 +6,8 @@ #include #include -extern const struct hwrtc* sysrtc; -extern const struct hwtimer* systimer; - -void -clock_init(); +extern const struct hwrtc_potens* sysrtc; +extern const struct hwtimer_pot* systimer; void clock_walltime(datetime_t* datetime); @@ -26,4 +23,10 @@ clock_systime(); time_t clock_unixtime(); +static inline void +clock_init() +{ + hwrtc_init(); +} + #endif /* __LUNAIX_CLOCK_H */ diff --git a/lunaix-os/includes/lunaix/compiler.h b/lunaix-os/includes/lunaix/compiler.h index 178c0fe..ffc73c8 100644 --- a/lunaix-os/includes/lunaix/compiler.h +++ b/lunaix-os/includes/lunaix/compiler.h @@ -7,14 +7,14 @@ #define __section(name) __attribute__((section(name))) #define weak_alias(name) __attribute__((weak, alias(name))) #define optimize(opt) __attribute__((optimize(opt))) -#define weak __attribute__((weak)) +#define _weak __attribute__((weak)) #define noret __attribute__((noreturn)) #define must_inline __attribute__((always_inline)) #define must_emit __attribute__((used)) #define unreachable __builtin_unreachable() #define no_inline __attribute__((noinline)) -#define _default weak +#define _default _weak #define msbiti (sizeof(int) * 8 - 1) #define clz(bits) __builtin_clz(bits) diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index 287cdad..f1ce4d0 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -1,7 +1,7 @@ #ifndef __LUNAIX_DEVICE_H #define __LUNAIX_DEVICE_H -#define DEVICE_NAME_SIZE 32 +#define DEVICE_NAME_SIZE 16 #include #include @@ -11,6 +11,9 @@ #include #include #include +#include + +#include #include @@ -40,13 +43,6 @@ */ #define load_sysconf ld_sysconf -/** - * @brief Mark the device definition should be loaded as time device, for - * example a real time clock device. Such device will be loaded and managed by - * clock subsystem - */ -#define load_timedev ld_timedev - /** * @brief Mark the device definition should be loaded automatically during the * bootstrapping stage. Most of the driver do load there. @@ -72,89 +68,110 @@ * @brief Declare a device class * */ -#define DEVCLASS(devif, devfn, dev) \ +#define DEVCLASS(vendor, devfn, dev) \ (struct devclass) \ { \ - .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), .variant = 0 \ + .fn_grp = DEV_FNGRP(dev_vn(vendor), dev_fn(devfn)), \ + .device = dev_id(dev), .variant = 0 \ } -#define DEVCLASSV(devif, devfn, dev, devvar) \ - (struct devclass) \ - { \ - .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), \ - .variant = (devvar) \ - } - -#define DEV_STRUCT_MAGIC_MASK 0x56454440U -#define DEV_STRUCT 0xc -#define DEV_CAT 0xd -#define DEV_ALIAS 0xf - -#define DEV_STRUCT_MAGIC (DEV_STRUCT_MAGIC_MASK | DEV_STRUCT) -#define DEV_CAT_MAGIC (DEV_STRUCT_MAGIC_MASK | DEV_CAT) -#define DEV_ALIAS_MAGIC (DEV_STRUCT_MAGIC_MASK | DEV_ALIAS) - #define DEV_MSKIF 0x00000003 - #define DEV_IFVOL 0x0 // volumetric (block) device #define DEV_IFSEQ 0x1 // sequential (character) device #define DEV_IFSYS 0x3 // a system device -struct capability_meta +#define dev_object_root \ + ({ extern morph_t* device_mobj_root; device_mobj_root; }) + +/** + * A potens is a capability of the device + * ("potens", means "capable" in latin) + * + * A device can have multiple capabilities + * (or "potentes", plural form of potens) + * + * A group of devices with same capability will forms + * a "globus potentis" or "capability group". The + * group is completely a logical formation, meaning + * that it is not explictly coded. + * + * The idea of potens is to provide a unified and yet + * opaque method to decouple the device provide raw + * functionalities with any higher abstraction, such + * as other subsystem, or standard-compilance wrapper + * (e.g., POSIX terminal) + */ +struct potens_meta { - struct llist_header caps; - unsigned int cap_type; + struct device* owner; + + struct llist_header potentes; + unsigned int pot_type; }; -#define CAPABILITY_META \ - union { \ - struct capability_meta cap_meta; \ - struct { \ - struct llist_header caps; \ - unsigned int cap_type; \ - }; \ +#define POTENS_META \ + struct { \ + union { \ + struct potens_meta pot_meta; \ + struct { \ + struct llist_header potentes; \ + unsigned int pot_type; \ + }; \ + }; \ } -#define get_capability(cap, cap_type) \ - container_of((cap), cap_type, cap_meta) -#define cap_meta(cap) (&(cap)->cap_meta) +#define get_potens(cap, pot_struct) \ + container_of((cap), pot_struct, pot_meta) +#define potens_meta(cap) (&(cap)->pot_meta) +#define potens_dev(cap) (potens_meta(cap)->owner) -typedef struct llist_header capability_list_t; +#define potens(name) POTENS_##name +#define potens_check_unique(dev, pot_type) \ + !device_get_potens(dev, pot_type) -struct device_meta +enum device_potens_type { - u32_t magic; - struct llist_header siblings; - struct llist_header children; - struct device_meta* parent; - struct hstr name; - - u32_t dev_uid; - - char name_val[DEVICE_NAME_SIZE]; + potens(NON), + #include }; +/** + * List of potentes of a device, pay attention to + * the spelling, "potentium", genitive plural of "potens". + */ +typedef struct llist_header potentium_list_t; + + +#define DEVICE_META_FIELD \ + struct { \ + morph_t mobj; \ + char name_val[DEVICE_NAME_SIZE]; \ + }; + #define DEVICE_METADATA \ union { \ struct device_meta meta; \ - struct { \ - u32_t magic; \ - struct llist_header siblings; \ - struct llist_header children; \ - struct device_meta* parent; \ - struct hstr name; \ - \ - u32_t dev_uid; \ - \ - char name_val[DEVICE_NAME_SIZE]; \ - }; \ - } - -#define dev_meta(dev) (&(dev)->meta) -#define to_dev(dev) (container_of(dev,struct device, meta)) -#define to_catdev(dev) (container_of(dev,struct device_cat, meta)) -#define to_aliasdev(dev) (container_of(dev,struct device_alias, meta)) + DEVICE_META_FIELD; \ + } + +#define devmeta_morpher morphable_attrs(device_meta, mobj) +#define devalias_morpher morphable_attrs(device_alias, mobj) +#define devcat_morpher morphable_attrs(device_cat, mobj) +#define device_morpher morphable_attrs(device, mobj) + +#define dev_meta(dev) (&(dev)->meta) +#define dev_mobj(dev) (&(dev)->mobj) +#define dev_morph(dev) ({ likely(dev) ? &(dev)->mobj : dev_object_root; }) +#define dev_uid(dev) (morpher_uid(&(dev)->mobj)) +#define to_dev(dev) (container_of(dev,struct device, meta)) +#define to_catdev(dev) (container_of(dev,struct device_cat, meta)) +#define to_aliasdev(dev) (container_of(dev,struct device_alias, meta)) + +struct device_meta +{ + DEVICE_META_FIELD; +}; struct device_alias { DEVICE_METADATA; @@ -171,7 +188,11 @@ struct device DEVICE_METADATA; - capability_list_t capabilities; + potentium_list_t potentium; + +#ifdef CONFIG_USE_DEVICETREE + devtree_link_t devtree_node; +#endif /* -- device state -- */ @@ -204,6 +225,15 @@ struct device } ops; }; +struct device_def; +typedef int (*devdef_ldfn)(struct device_def*); + +struct device_ldfn_chain +{ + struct device_ldfn_chain* chain; + devdef_ldfn load; +}; + struct device_def { struct llist_header dev_list; @@ -211,20 +241,46 @@ struct device_def struct hlist_node hlist_if; char* name; - struct devclass class; + union + { + struct { + bool no_default_realm : 1; + }; + int val; + } flags; + + + struct { + struct devclass class; + unsigned int class_hash; + }; + + struct device_ldfn_chain* load_chain; /** - * @brief Called when the driver is required to initialize itself. + * @brief + * Called when driver is required to register itself to the system + * All registration code should put it here. + * + * ad tabulam - + * "to the record" in latin. just in case anyone wonders. + * I am ran out of naming idea... have to improvise :) * */ - int (*init)(struct device_def*); + devdef_ldfn ad_tabulam; /** - * @brief Called when the driver is required to bind with a device. This is - * the case for a real-hardware-oriented driver + * @brief Called when the driver is loaded at it's desired load stage * */ - int (*bind)(struct device_def*, struct device*); + devdef_ldfn load; + + /** + * @brief Called when the driver is required to create device instance + * This is for device with their own preference of creation + * object that hold parameter for such creation is provided by second argument. + */ + int (*create)(struct device_def*, morph_t*); /** * @brief Called when a driver is requested to detach from the device and @@ -234,29 +290,16 @@ struct device_def int (*free)(struct device_def*, void* instance); }; -static inline bool must_inline -valid_device_ref(void* maybe_dev) { - if (!maybe_dev) - return false; - - unsigned int magic = ((struct device_meta*)maybe_dev)->magic; - return (magic ^ DEV_STRUCT_MAGIC_MASK) <= 0xfU; -} - -static inline bool must_inline -valid_device_subtype_ref(void* maybe_dev, unsigned int subtype) { - if (!maybe_dev) - return false; - - unsigned int magic = ((struct device_meta*)maybe_dev)->magic; - return (magic ^ DEV_STRUCT_MAGIC_MASK) == subtype; -} - -struct device* -resolve_device(void* maybe_dev); +#define def_device_name(dev_n) .name = dev_n +#define def_device_class(_if, fn, dev) .class = DEVCLASS(_if, fn, dev) +#define def_on_register(fn) .ad_tabulam = fn +#define def_on_load(fn) .load = fn +#define def_on_create(fn) .create = fn +#define def_on_free(fn) .free = fn +#define def_non_trivial .flags.no_default_realm = true -struct device_meta* -resolve_device_meta(void* maybe_dev); +morph_t* +resolve_device_morph(void* maybe_dev); #define mark_device_doing_write(dev_ptr) (dev_ptr)->poll_evflags &= ~_POLLOUT #define mark_device_done_write(dev_ptr) (dev_ptr)->poll_evflags |= _POLLOUT @@ -273,6 +316,12 @@ device_id_from_class(struct devclass* class) return ((class->device & 0xffff) << 16) | ((class->variant & 0xffff)); } +static inline struct device* +resolve_device(void* maybe_dev) { + morph_t* mobj = resolve_device_morph(maybe_dev); + return changeling_try_reveal(mobj, device_morpher); +} + void device_scan_drivers(); @@ -283,11 +332,18 @@ void device_setname(struct device_meta* dev, char* fmt, ...); void -device_register_generic(struct device_meta* dev, struct devclass* class, char* fmt, ...); +device_register_generic(struct device_meta* dev, struct devclass* class, + char* fmt, ...); #define register_device(dev, class, fmt, ...) \ device_register_generic(dev_meta(dev), class, fmt, ## __VA_ARGS__) +#define register_device_var(dev, class, fmt, ...) \ + ({device_register_generic( \ + dev_meta(dev), class, \ + fmt "%d", ## __VA_ARGS__, (class)->variant); \ + devclass_mkvar(class); }) + void device_create(struct device* dev, struct device_meta* parent, @@ -297,6 +353,12 @@ device_create(struct device* dev, struct device* device_alloc(struct device_meta* parent, u32_t type, void* underlay); +static inline void +device_set_devtree_node(struct device* dev, devtree_link_t node) +{ + dev->devtree_node = node; +} + static inline struct device* must_inline device_allocsys(struct device_meta* parent, void* underlay) { @@ -316,7 +378,8 @@ device_allocvol(struct device_meta* parent, void* underlay) } struct device_alias* -device_addalias(struct device_meta* parent, struct device_meta* aliased, char* name_fmt, ...); +device_addalias(struct device_meta* parent, struct device_meta* aliased, + char* name_fmt, ...); struct device_cat* device_addcat(struct device_meta* parent, char* name_fmt, ...); @@ -324,18 +387,6 @@ device_addcat(struct device_meta* parent, char* name_fmt, ...); void device_remove(struct device_meta* dev); -struct device_meta* -device_getbyid(struct llist_header* devlist, u32_t id); - -struct device_meta* -device_getbyhname(struct device_meta* root_dev, struct hstr* name); - -struct device_meta* -device_getbyname(struct device_meta* root_dev, const char* name, size_t len); - -struct device_meta* -device_getbyoffset(struct device_meta* root_dev, int pos); - struct hbucket* device_definitions_byif(int if_type); @@ -350,20 +401,21 @@ device_scan_drivers(); /*------ Capability ------*/ -struct capability_meta* -alloc_capability(int cap, unsigned int size); +struct potens_meta* +alloc_potens(int cap, unsigned int size); -#define new_capability(cap_type, cap_impl)\ - ((cap_impl*)alloc_capability((cap_type), sizeof(cap_impl))) +#define new_potens(pot_type, pot_struct)\ + ((pot_struct*)alloc_potens((pot_type), sizeof(pot_struct))) -#define new_capability_marker(cap_type)\ - (alloc_capability((cap_type), sizeof(struct capability_meta))) +#define new_potens_marker(pot_type)\ + (alloc_potens((pot_type), sizeof(struct potens_meta))) void -device_grant_capability(struct device* dev, struct capability_meta* cap); +device_grant_potens(struct device* dev, struct potens_meta* cap); + +struct potens_meta* +device_get_potens(struct device* dev, unsigned int pot_type); -struct capability_meta* -device_get_capability(struct device* dev, unsigned int cap_type); /*------ Load hooks ------*/ void @@ -375,6 +427,21 @@ device_postboot_load(); void device_sysconf_load(); +/** + * @brief Add the loader to the chain, used by device domain + * to inject their custom loading logic to the hook + */ +void +device_chain_loader(struct device_def* def, devdef_ldfn fn); + +/** + * @brief Walk the chain and load in a use-and-burnt fashion. + * the chain will be deleted and freed after loading, + * regardless successful or not. + */ +void +device_chain_load_once(struct device_def* def); + static inline void device_lock(struct device* dev) { @@ -395,4 +462,42 @@ device_locked(struct device* dev) #define devprintf_expand(devident) (devident)->fn_grp, (devident)->unique + +/** + * + * Device def hooks extern + * + */ + +static int +default_onregister_hook(struct device_def* def) +{ + return 0; +} + +static int +default_onload_hook(struct device_def* def) +{ + return 0; +} + +static int +default_oncreate_hook(struct device_def* def, morph_t* morphed) +{ + return 0; +} + +#define extern_hook_register(name) \ + int weak_alias("default_onregister_hook") \ + name(struct device_def* def) + +#define extern_hook_load(name) \ + int weak_alias("default_onload_hook") \ + name(struct device_def* def) + +#define extern_hook_create(name) \ + int weak_alias("default_oncreate_hook") \ + name(struct device_def* def, morph_t* morphed) + + #endif /* __LUNAIX_DEVICE_H */ diff --git a/lunaix-os/includes/lunaix/device_num.h b/lunaix-os/includes/lunaix/device_num.h index b59c857..eef7989 100644 --- a/lunaix-os/includes/lunaix/device_num.h +++ b/lunaix-os/includes/lunaix/device_num.h @@ -58,57 +58,37 @@ */ -#define DEV_FNGRP(if_, function) \ - (((if_) & 0xffff) << 16) | ((function) & 0xffff) +#define DEV_FNGRP(vendor, function) \ + (((vendor) & 0xffff) << 16) | ((function) & 0xffff) #define DEV_UNIQUE(devkind, variant) \ (((devkind) & 0xffff) << 16) | ((variant) & 0xffff) #define DEV_KIND_FROM(unique) ((unique) >> 16) #define DEV_VAR_FROM(unique) ((unique) & 0xffff) -#define DEV_IF(fngrp) ((fngrp) >> 16) +#define DEV_VN(fngrp) ((fngrp) >> 16) #define DEV_FN(fngrp) (((fngrp) & 0xffff)) -#define DEVIF_NON 0x0 -#define DEVIF_SOC 0x1 -#define DEVIF_PCI 0x2 -#define DEVIF_USB 0x3 -#define DEVIF_SPI 0x4 -#define DEVIF_I2C 0x5 -#define DEVIF_FMW 0x6 - -#define DEVFN_PSEUDO 0x0 -#define DEVFN_CHAR 0x1 -#define DEVFN_STORAGE 0x4 -#define DEVFN_INPUT 0x5 -#define DEVFN_TIME 0x6 -#define DEVFN_BUSIF 0x7 -#define DEVFN_TTY 0x8 -#define DEVFN_DISP 0x9 -#define DEVFN_CFG 0xa - -#define DEV_BUILTIN 0 -#define DEV_BUILTIN_NULL 0 -#define DEV_BUILTIN_ZERO 1 -#define DEV_BUILTIN_KMSG 2 - -#define DEV_VTERM 1 -#define DEV_RNG 2 -#define DEV_RTC 3 -#define DEV_SATA 4 -#define DEV_NVME 5 -#define DEV_PCI 6 -#define DEV_UART16550 7 - -#define DEV_TIMER 8 -#define DEV_TIMER_APIC 0 -#define DEV_TIMER_HEPT 1 - -#define DEV_NULL 9 -#define DEV_ZERO 10 -#define DEV_KBD 11 -#define DEV_GFXA 12 -#define DEV_VGA 13 -#define DEV_ACPI 14 +#define dev_vn(x) DEVVN_##x +#define dev_fn(x) DEVFN_##x +#define dev_id(x) DEV_##x + +enum devnum_vn +{ + dev_vn(GENERIC), + #include +}; + +enum devnum_fn +{ + dev_fn(NON), + #include +}; + +enum devnum +{ + dev_id(NON), + #include +}; struct devident { @@ -121,7 +101,12 @@ struct devclass u32_t fn_grp; u32_t device; u32_t variant; - u32_t hash; }; +static inline int +devclass_mkvar(struct devclass* class) +{ + return class->variant++; +} + #endif /* __LUNAIX_DEVICE_NUM_H */ diff --git a/lunaix-os/includes/lunaix/ds/list.h b/lunaix-os/includes/lunaix/ds/list.h new file mode 100644 index 0000000..288ee66 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/list.h @@ -0,0 +1,67 @@ +/** + * @file slist.h + * @author Lunaixsky + * @brief This singly linked list is adopted from Linux kernel + * + * @version 0.1 + * @date 2022-03-12 + * + * @copyright Copyright (c) 2024 + * + */ +#ifndef __LUNAIX_LIST_H +#define __LUNAIX_LIST_H + +#include + +struct list_head { + struct list_node *first; +}; + +struct list_node { + struct list_node *next; +}; + +#define DEFINE_LIST(name) struct list_head name = { .first = NULL } + +static inline void +list_head_init(struct list_head *list) +{ + list->first = NULL; +} + +static inline void +list_node_init(struct list_node *node) +{ + node->next = node; +} + +#define slist_entry(ptr, type, member) \ + container_of(ptr, type, member) + +#define member_address_is_nonnull(ptr, member) \ + ((ptr_t)(ptr) + offsetof(typeof(*(ptr)), member) != 0) + +#define list_for_each(pos, n, node, member) \ + for (pos = slist_entry((node), typeof(*pos), member); \ + member_address_is_nonnull(pos, member) && \ + (n = slist_entry(pos->member.next, typeof(*n), member), true); \ + pos = n) + +static inline bool +__llist_add_batch(struct list_node *new_first, + struct list_node *new_last, + struct list_head *head) +{ + new_last->next = head->first; + head->first = new_first; + return new_last->next == NULL; +} + +static inline void +list_add(struct list_head* head, struct list_node* node) +{ + __llist_add_batch(node, node, head); +} + +#endif /* __LUNAIX_LIST_H */ diff --git a/lunaix-os/includes/lunaix/owloysius.h b/lunaix-os/includes/lunaix/owloysius.h index 22311bb..99cffa2 100644 --- a/lunaix-os/includes/lunaix/owloysius.h +++ b/lunaix-os/includes/lunaix/owloysius.h @@ -7,6 +7,12 @@ * @brief stage where only basic memory management service * is present */ +#define on_sysconf c_sysconf + +/** + * @brief stage where basic memory management service + * interrupt management and timer/clock service avaliable + */ #define on_earlyboot c_earlyboot /** @@ -29,4 +35,28 @@ #define invoke_init_function(stage) ldga_invoke_fn0(lunainit##_##stage) +static inline void +initfn_invoke_sysconf() +{ + invoke_init_function(on_sysconf); +} + +static inline void +initfn_invoke_earlyboot() +{ + invoke_init_function(on_earlyboot); +} + +static inline void +initfn_invoke_boot() +{ + invoke_init_function(on_boot); +} + +static inline void +initfn_invoke_postboot() +{ + invoke_init_function(on_postboot); +} + #endif /* __LUNAIX_OWLOYSIUS_H */ diff --git a/lunaix-os/includes/lunaix/sections.h b/lunaix-os/includes/lunaix/sections.h index 3182825..c164f0c 100644 --- a/lunaix-os/includes/lunaix/sections.h +++ b/lunaix-os/includes/lunaix/sections.h @@ -12,7 +12,7 @@ /* Auto-generated data */ #define extern_autogen(name) \ - weak unsigned long __mark_name(autogen,name)[] = {}; \ + _weak unsigned long __mark_name(autogen,name)[] = {}; \ extern unsigned long __mark_name(autogen,name)[]; #define autogen_name(name) __mark_name(autogen,name) diff --git a/lunaix-os/includes/lunaix/timer.h b/lunaix-os/includes/lunaix/timer.h index 08718ad..fbbe2b7 100644 --- a/lunaix-os/includes/lunaix/timer.h +++ b/lunaix-os/includes/lunaix/timer.h @@ -9,32 +9,6 @@ #define TIMER_MODE_PERIODIC 0x1 -struct lx_timer_context -{ - struct lx_timer* active_timers; - /** - * @brief timer hardware base frequency (ticks per seconds) - * - */ - ticks_t base_frequency; - /** - * @brief Desired system running frequency - * - */ - ticks_t running_frequency; - /** - * @brief Ticks per hertz - * - */ - ticks_t tphz; -}; - -struct timer_init_param -{ - struct lx_timer_context* context; - void* timer_update_isr; -}; - struct lx_timer { struct llist_header link; @@ -68,7 +42,4 @@ timer_run_ms(u32_t millisecond, struct lx_timer* timer_run(ticks_t ticks, void (*callback)(void*), void* payload, u8_t flags); -struct lx_timer_context* -timer_context(); - #endif /* __LUNAIX_TIMER_H */ diff --git a/lunaix-os/kernel/LBuild b/lunaix-os/kernel/LBuild index a71dd8b..8e92773 100644 --- a/lunaix-os/kernel/LBuild +++ b/lunaix-os/kernel/LBuild @@ -16,6 +16,7 @@ sources([ "lrud.c", "bcache.c", "syscall.c", + "changeling.c", "kprint/kp_records.c", "kprint/kprintf.c", "time/clock.c", diff --git a/lunaix-os/kernel/block/blkbuf.c b/lunaix-os/kernel/block/blkbuf.c index 862a48e..bb29150 100644 --- a/lunaix-os/kernel/block/blkbuf.c +++ b/lunaix-os/kernel/block/blkbuf.c @@ -244,4 +244,4 @@ __init_blkbuf() bb_zone = bcache_create_zone("blk_buf"); bb_pile = cake_new_pile("blk_buf", sizeof(struct blk_buf), 1, 0); } -owloysius_fetch_init(__init_blkbuf, on_earlyboot) \ No newline at end of file +owloysius_fetch_init(__init_blkbuf, on_sysconf) \ No newline at end of file diff --git a/lunaix-os/kernel/changeling.c b/lunaix-os/kernel/changeling.c new file mode 100644 index 0000000..ff81597 --- /dev/null +++ b/lunaix-os/kernel/changeling.c @@ -0,0 +1,79 @@ +#include +#include + +#include + +static DEFINE_LLIST(chrysallidis); +static unsigned int current_id = 0; + +void +changeling_init(morph_t* parent, morph_t* chlg, + unsigned int id, const char* name) +{ + chlg->sig = CHLG_ID; + chlg->ident = id; + chlg->ref = 1; + chlg->uid = current_id++; + + changeling_setname(chlg, name); + + if (!parent) { + llist_append(&chrysallidis, &chlg->sibs); + } else { + llist_append(&parent->subs, &chlg->sibs); + } + + llist_init_head(&chlg->subs); +} + +morph_t* +changeling_spawn(morph_t* parent, const char *name) +{ + morph_t* changeling; + + changeling = valloc(sizeof(morph_t)); + changeling_init(parent, changeling, chlg_anon, name); + + return changeling; +} + +morph_t* +changeling_find(morph_t* parent, struct hstr* str) +{ + morph_t *p, *n; + llist_for_each(p, n, &parent->subs, sibs) + { + if (HSTR_EQ(&p->name, str)) { + return p; + } + } + + return NULL; +} + +morph_t* +changeling_get_at(morph_t* parent, int index) +{ + morph_t *p, *n; + llist_for_each(p, n, &parent->subs, sibs) + { + if (!(index--)) { + return p; + } + } + + return NULL; +} + +morph_t* +changeling_setname(morph_t* chlg, const char* name) +{ + if (name) { + chlg->name = HSTR(name, strlen(name)); + hstr_rehash(&chlg->name, HSTR_FULL_HASH); + } else { + chlg->name = HHSTR(NULL, 0, 0); + } + + return chlg; +} \ No newline at end of file diff --git a/lunaix-os/kernel/device/LBuild b/lunaix-os/kernel/device/LBuild index c3c7255..989a81b 100644 --- a/lunaix-os/kernel/device/LBuild +++ b/lunaix-os/kernel/device/LBuild @@ -1,8 +1,8 @@ sources([ "device.c", - "capability.c", + "potentem.c", "devdb.c", "devfs.c", "input.c", - "poll.c" + "poll.c", ]) diff --git a/lunaix-os/kernel/device/capability.c b/lunaix-os/kernel/device/capability.c deleted file mode 100644 index b31f914..0000000 --- a/lunaix-os/kernel/device/capability.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -struct capability_meta* -alloc_capability(int cap, unsigned int size) -{ - struct capability_meta* cm = (struct capability_meta*)vzalloc(size); - - cm->cap_type = cap; - - return cm; -} - -void -device_grant_capability(struct device* dev, struct capability_meta* cap) -{ - llist_append(&dev->capabilities, &cap->caps); -} - -struct capability_meta* -device_get_capability(struct device* dev, unsigned int cap_type) -{ - struct capability_meta *pos, *n; - - llist_for_each(pos, n, &dev->capabilities, caps) { - if (pos->cap_type == cap_type){ - return pos; - } - } - - return NULL; -} \ No newline at end of file diff --git a/lunaix-os/kernel/device/devdb.c b/lunaix-os/kernel/device/devdb.c index 09b6b5c..a248378 100644 --- a/lunaix-os/kernel/device/devdb.c +++ b/lunaix-os/kernel/device/devdb.c @@ -1,11 +1,14 @@ #include #include #include +#include #include #include +LOG_MODULE("devdb") + static DECLARE_HASHTABLE(dev_registry, 32); static DECLARE_HASHTABLE(dev_byif, 8); static DEFINE_LLIST(dev_registry_flat); @@ -26,20 +29,33 @@ device_scan_drivers() hashtable_init(dev_registry); hashtable_init(dev_byif); - int idx = 0; + int idx = 0, errno; struct device_def* devdef; ldga_foreach(devdefs, struct device_def*, idx, devdef) { struct devclass* devc = &devdef->class; u32_t hash = hash_dev(devc->fn_grp, devc->device); - devc->hash = hash; + devdef->class_hash = hash; if (!devdef->name) { devdef->name = ""; } + errno = 0; + if (devdef->ad_tabulam) { + errno = devdef->ad_tabulam(devdef); + } + + if (errno) { + ERROR("driver unable to register %xh:%xh.%d (err=%d)", + devdef->class.fn_grp, + devdef->class.device, + devdef->class.variant, errno); + continue; + } + hashtable_hash_in(dev_registry, &devdef->hlist, hash); - hashtable_hash_in(dev_byif, &devdef->hlist_if, DEV_IF(devc->fn_grp)); + hashtable_hash_in(dev_byif, &devdef->hlist_if, DEV_VN(devc->fn_grp)); llist_append(&dev_registry_flat, &devdef->dev_list); } @@ -60,7 +76,7 @@ devdef_byclass(struct devclass* devc) struct device_def *pos, *n; hashtable_hash_foreach(dev_registry, hash, pos, n, hlist) { - if (pos->class.hash != hash) { + if (pos->class_hash != hash) { continue; } if (devclass_eq(devc, &pos->class)) { @@ -91,7 +107,7 @@ device_definitions_byif(int if_type) struct device_def* devdef; \ ldga_foreach(dev_##stage, struct device_def*, idx, devdef) \ { \ - devdef->init(devdef); \ + device_chain_load_once(devdef); \ } \ }) #define device_load_on_stage(stage) __device_load_on_stage(stage) @@ -133,7 +149,7 @@ __devdb_twifs_lsdb(struct twimap* mapping) struct device_def* def = twimap_index(mapping, struct device_def*); int meta = def->class.fn_grp; - ksnprintf(flags, 64, "if=%x,fn=%x", DEV_IF(meta), DEV_FN(meta)); + ksnprintf(flags, 64, "vn=%x, fn=%x", DEV_VN(meta), DEV_FN(meta)); twimap_printf(mapping, "%08xh:%04d \"%s\" %s\n", diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c index 28f923a..c105f66 100644 --- a/lunaix-os/kernel/device/devfs.c +++ b/lunaix-os/kernel/device/devfs.c @@ -65,17 +65,21 @@ devfs_write_page(struct v_inode* inode, void* buffer, size_t fpos) } int -devfs_get_itype(struct device_meta* dm) +devfs_get_itype(morph_t* obj) { int itype = VFS_IFDEV; - if (valid_device_subtype_ref(dm, DEV_CAT)) { + if (morph_type_of(obj, devcat_morpher)) { return VFS_IFDIR; } - struct device* dev = resolve_device(dm); - int dev_if = dev->dev_type & DEV_MSKIF; + struct device* dev = resolve_device(obj); + + if (!dev) { + return itype; + } + int dev_if = dev->dev_type & DEV_MSKIF; if (dev_if == DEV_IFVOL) { itype |= VFS_IFVOLDEV; } @@ -84,26 +88,38 @@ devfs_get_itype(struct device_meta* dm) return itype; } -int -devfs_get_dtype(struct device_meta* dev) +static inline int +devfs_get_dtype(morph_t* dev_morph) { - if (valid_device_subtype_ref(dev, DEV_CAT)) { + if (morph_type_of(dev_morph, devcat_morpher)) { return DT_DIR; } return DT_FILE; } +static inline morph_t* +__try_resolve(struct v_inode* inode) +{ + if (!inode->data) { + return dev_object_root; + } + + return resolve_device_morph(inode->data); +} + int -devfs_mknod(struct v_dnode* dnode, struct device_meta* dev) +devfs_mknod(struct v_dnode* dnode, morph_t* obj) { - assert(dev); + struct v_inode* devnod; + + assert(obj); - struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_uid); + devnod = vfs_i_find(dnode->super_block, morpher_uid(obj)); if (!devnod) { if ((devnod = vfs_i_alloc(dnode->super_block))) { - devnod->id = dev->dev_uid; - devnod->data = dev; - devnod->itype = devfs_get_itype(dev); + devnod->id = morpher_uid(obj); + devnod->data = changeling_ref(obj); + devnod->itype = devfs_get_itype(obj); vfs_i_addhash(devnod); } else { @@ -118,30 +134,28 @@ devfs_mknod(struct v_dnode* dnode, struct device_meta* dev) int devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) { - void* data = this->data; - struct device_meta* rootdev = resolve_device_meta(data); + morph_t *mobj, *root; - if (data && !rootdev) { + root = __try_resolve(this); + if (!root) { return ENOTDIR; } - struct device_meta* dev = - device_getbyhname(rootdev, &dnode->name); - - if (!dev) { + mobj = changeling_find(root, &dnode->name); + if (!mobj) { return ENOENT; } - return devfs_mknod(dnode, dev); + return devfs_mknod(dnode, mobj); } int devfs_readdir(struct v_file* file, struct dir_context* dctx) { - void* data = file->inode->data; - struct device_meta* rootdev = resolve_device_meta(data); + morph_t *mobj, *root; - if (data && !rootdev) { + root = __try_resolve(file->inode); + if (!root) { return ENOTDIR; } @@ -149,15 +163,14 @@ devfs_readdir(struct v_file* file, struct dir_context* dctx) return 1; } - struct device_meta* dev = - device_getbyoffset(rootdev, file->f_pos - 2); - - if (!dev) { + mobj = changeling_get_at(root, file->f_pos - 2); + if (!mobj) { return 0; } - dctx->read_complete_callback( - dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev)); + dctx->read_complete_callback(dctx, + mobj->name.value, mobj->name.len, + devfs_get_dtype(mobj)); return 1; } diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index d32ca32..9af8ac3 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -1,4 +1,3 @@ - #include #include #include @@ -7,77 +6,61 @@ #include #include #include +#include #include #include static DEFINE_LLIST(root_list); -static volatile u32_t devid = 0; - -struct devclass default_devclass = {}; +morph_t* device_mobj_root; void device_setname_vargs(struct device_meta* dev, char* fmt, va_list args) { - size_t strlen = ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args); - - dev->name = HSTR(dev->name_val, strlen); - - hstr_rehash(&dev->name, HSTR_FULL_HASH); + ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args); + changeling_setname(dev_mobj(dev), dev->name_val); } void -device_register_generic(struct device_meta* devm, struct devclass* class, char* fmt, ...) +device_register_generic(struct device_meta* devm, struct devclass* class, + char* fmt, ...) { va_list args; + morph_t* morphed, *parent; + + morphed = &devm->mobj; va_start(args, fmt); if (fmt) { device_setname_vargs(devm, fmt, args); } - if (class && valid_device_subtype_ref(devm, DEV_STRUCT)) { + if (class && morph_type_of(morphed, device_morpher)) + { struct device* dev = to_dev(devm); - dev->ident = (struct devident){ .fn_grp = class->fn_grp, - .unique = DEV_UNIQUE(class->device, - class->variant) }; + dev->ident = (struct devident) { + .fn_grp = class->fn_grp, + .unique = DEV_UNIQUE(class->device, class->variant) + }; } - devm->dev_uid = devid++; - - struct device_meta* parent = devm->parent; + parent = morphed->parent; if (parent) { - assert(valid_device_subtype_ref(parent, DEV_CAT)); - llist_append(&parent->children, &devm->siblings); - } else { - llist_append(&root_list, &devm->siblings); + changeling_attach(parent, morphed); } va_end(args); } -static void -device_init_meta(struct device_meta* dmeta, struct device_meta* parent, unsigned int subtype) -{ - dmeta->magic = DEV_STRUCT_MAGIC_MASK | subtype; - dmeta->parent = parent; - - llist_init_head(&dmeta->children); -} - void -device_create(struct device* dev, - struct device_meta* parent, - u32_t type, - void* underlay) +device_create(struct device* dev, struct device_meta* parent, + u32_t type, void* underlay) { - dev->magic = DEV_STRUCT_MAGIC; dev->underlay = underlay; dev->dev_type = type; - device_init_meta(dev_meta(dev), parent, DEV_STRUCT); - llist_init_head(&dev->capabilities); + llist_init_head(&dev->potentium); mutex_init(&dev->lock); iopoll_init_evt_q(&dev->pollers); } @@ -92,6 +75,7 @@ device_alloc(struct device_meta* parent, u32_t type, void* underlay) } device_create(dev, parent, type, underlay); + changeling_morph(dev_morph(parent), dev->mobj, NULL, device_morpher); return dev; } @@ -105,8 +89,9 @@ device_alloc_alias(struct device_meta* parent, struct device_meta* aliased) return NULL; } - device_init_meta(dev_meta(dev), parent, DEV_ALIAS); dev->alias = aliased; + changeling_ref(dev_mobj(aliased)); + changeling_morph(dev_morph(parent), dev->mobj, NULL, devalias_morpher); return dev; } @@ -120,12 +105,11 @@ device_alloc_cat(struct device_meta* parent) return NULL; } - device_init_meta(dev_meta(dev), parent, DEV_CAT); + changeling_morph(dev_morph(parent), dev->mobj, NULL, devcat_morpher); return dev; } - void device_setname(struct device_meta* dev, char* fmt, ...) { @@ -153,7 +137,8 @@ device_addcat(struct device_meta* parent, char* name_fmt, ...) } struct device_alias* -device_addalias(struct device_meta* parent, struct device_meta* aliased, char* name_fmt, ...) +device_addalias(struct device_meta* parent, + struct device_meta* aliased, char* name_fmt, ...) { va_list args; va_start(args, name_fmt); @@ -167,67 +152,13 @@ device_addalias(struct device_meta* parent, struct device_meta* aliased, char* n return dev; } -struct device_meta* -device_getbyid(struct llist_header* devlist, u32_t id) -{ - devlist = devlist ? devlist : &root_list; - struct device_meta *pos, *n; - llist_for_each(pos, n, devlist, siblings) - { - if (pos->dev_uid == id) { - return pos; - } - } - - return NULL; -} - -struct device_meta* -device_getbyhname(struct device_meta* root_dev, struct hstr* name) -{ - struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; - struct device_meta *pos, *n; - llist_for_each(pos, n, devlist, siblings) - { - if (HSTR_EQ(&pos->name, name)) { - return pos; - } - } - - return NULL; -} - -struct device_meta* -device_getbyname(struct device_meta* root_dev, const char* name, size_t len) -{ - struct hstr hname = HSTR(name, len); - hstr_rehash(&hname, HSTR_FULL_HASH); - - return device_getbyhname(root_dev, &hname); -} - void device_remove(struct device_meta* dev) { - llist_delete(&dev->siblings); + changeling_isolate(&dev->mobj); vfree(dev); } -struct device_meta* -device_getbyoffset(struct device_meta* root_dev, int offset) -{ - struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; - struct device_meta *pos, *n; - int off = 0; - llist_for_each(pos, n, devlist, siblings) - { - if (off++ >= offset) { - return pos; - } - } - return NULL; -} - void device_populate_info(struct device* dev, struct dev_info* devinfo) { @@ -245,44 +176,35 @@ device_populate_info(struct device* dev, struct dev_info* devinfo) devinfo->dev_name.buf[buflen - 1] = 0; } -struct device_meta* -resolve_device_meta(void* maybe_dev) { - if (!valid_device_ref(maybe_dev)) { +morph_t* +resolve_device_morph(void* maybe_dev) +{ + struct device_alias* da = NULL; + morph_t *morphed; + + morphed = morphed_ptr(maybe_dev); + + if (!is_changeling(morphed)) { return NULL; } - struct device_meta* dm = (struct device_meta*)maybe_dev; - unsigned int subtype = dm->magic ^ DEV_STRUCT_MAGIC_MASK; - - switch (subtype) + if (morph_type_of(morphed, device_morpher)) { - case DEV_STRUCT: - case DEV_CAT: - return dm; - - case DEV_ALIAS: { - struct device_meta* aliased_dm = dm; - - while(valid_device_subtype_ref(aliased_dm, DEV_ALIAS)) { - aliased_dm = to_aliasdev(aliased_dm)->alias; - } - - return aliased_dm; - } - default: - return NULL; + return morphed; } -} -struct device* -resolve_device(void* maybe_dev) { - struct device_meta* dm = resolve_device_meta(maybe_dev); - - if (!valid_device_subtype_ref(dm, DEV_STRUCT)) { - return NULL; + if (morph_type_of(morphed, devcat_morpher)) + { + return morphed; + } + + while(morph_type_of(morphed, devalias_morpher)) + { + da = changeling_reveal(morphed, devalias_morpher); + morphed = &da->alias->mobj; } - return to_dev(dm); + return da ? morphed : NULL; } void @@ -292,6 +214,57 @@ device_alert_poller(struct device* dev, int poll_evt) iopoll_wake_pollers(&dev->pollers); } +void +device_chain_loader(struct device_def* def, devdef_ldfn fn) +{ + struct device_ldfn_chain* node; + + node = valloc(sizeof(*node)); + node->load = fn; + + if (!def->load_chain) { + node->chain = NULL; + } + else { + node->chain = def->load_chain; + } + + def->load_chain = node; +} + +void +device_chain_load_once(struct device_def* def) +{ + struct device_ldfn_chain *node, *next; + + if (def->load) { + def->load(def); + } + + node = def->load_chain; + def->load_chain = NULL; + + while (node) + { + node->load(def); + next = node->chain; + vfree(node); + + node = next; + } + + if (def->flags.no_default_realm) { + return; + } + + if (!def->create) { + return; + } + + def->create(def, NULL); + +} + __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, sc_va_list, _args) { int errno = -1; @@ -305,7 +278,7 @@ __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, sc_va_list, _args) } struct device* dev = resolve_device(fd_s->file->inode->data); - if (!valid_device_subtype_ref(dev, DEV_STRUCT)) { + if (!dev) { errno = ENODEV; goto done; } @@ -325,4 +298,11 @@ __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, sc_va_list, _args) done: return DO_STATUS_OR_RETURN(errno); -} \ No newline at end of file +} + +static void +__device_subsys_init() +{ + device_mobj_root = changeling_spawn(NULL, "devices"); +} +owloysius_fetch_init(__device_subsys_init, on_sysconf); \ No newline at end of file diff --git a/lunaix-os/kernel/device/potentem.c b/lunaix-os/kernel/device/potentem.c new file mode 100644 index 0000000..b7de144 --- /dev/null +++ b/lunaix-os/kernel/device/potentem.c @@ -0,0 +1,33 @@ +#include +#include + +struct potens_meta* +alloc_potens(int cap, unsigned int size) +{ + struct potens_meta* cm = (struct potens_meta*)vzalloc(size); + + cm->pot_type = cap; + + return cm; +} + +void +device_grant_potens(struct device* dev, struct potens_meta* cap) +{ + llist_append(&dev->potentium, &cap->potentes); + cap->owner = dev; +} + +struct potens_meta* +device_get_potens(struct device* dev, unsigned int pot_type) +{ + struct potens_meta *pos, *n; + + llist_for_each(pos, n, &dev->potentium, potentes) { + if (pos->pot_type == pot_type){ + return pos; + } + } + + return NULL; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index 0f3b3fb..c673e84 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -288,6 +288,7 @@ __DEFINE_LXSYSCALL4(int, int, options) { + struct device* device = NULL; struct v_dnode *dev = NULL, *mnt = NULL; int errno = 0; @@ -308,16 +309,14 @@ __DEFINE_LXSYSCALL4(int, goto done; } - // By our convention. - // XXX could we do better? - struct device* device = NULL; - if (dev) { if (!check_voldev_node(dev->inode)) { errno = ENOTDEV; goto done; } - device = (struct device*)dev->inode->data; + + device = resolve_device(dev->inode->data); + assert(device); } errno = vfs_mount_at(fstype, device, mnt, options); diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 025fa3f..0eec6bf 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -1660,20 +1660,20 @@ __DEFINE_LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat) if (check_device_node(vino)) { struct device* rdev = resolve_device(vino->data); - if (!rdev || rdev->magic != DEV_STRUCT_MAGIC) { + if (!rdev) { errno = EINVAL; goto done; } stat->st_rdev = (dev_t){.meta = rdev->ident.fn_grp, .unique = rdev->ident.unique, - .index = rdev->dev_uid}; + .index = dev_uid(rdev) }; } if (fdev) { stat->st_dev = (dev_t){.meta = fdev->ident.fn_grp, .unique = fdev->ident.unique, - .index = fdev->dev_uid}; + .index = dev_uid(fdev) }; } done: diff --git a/lunaix-os/kernel/kinit.c b/lunaix-os/kernel/kinit.c index 16c7976..38804f2 100644 --- a/lunaix-os/kernel/kinit.c +++ b/lunaix-os/kernel/kinit.c @@ -123,7 +123,6 @@ kernel_bootstrap(struct boot_handoff* bhctx) /* Setup kernel memory layout and services */ kmem_init(bhctx); - __remap_and_load_dtb(bhctx); boot_parse_cmdline(bhctx); @@ -132,19 +131,19 @@ kernel_bootstrap(struct boot_handoff* bhctx) device_scan_drivers(); + initfn_invoke_sysconf(); + + __remap_and_load_dtb(bhctx); device_sysconf_load(); - invoke_init_function(on_earlyboot); + // TODO register devtree hooks + // TODO re-scan devtree to bind devices. clock_init(); timer_init(); - /* - TODO autoload these init function that do not have dependency between - them - */ + initfn_invoke_earlyboot(); - /* Let's get fs online as soon as possible, as things rely on them */ vfs_init(); fsm_init(); input_init(); @@ -158,7 +157,7 @@ kernel_bootstrap(struct boot_handoff* bhctx) must_success(vfs_mount_root("ramfs", NULL)); must_success(vfs_mount("/dev", "devfs", NULL, 0)); - invoke_init_function(on_boot); + initfn_invoke_boot(); /* Finish up bootstrapping sequence, we are ready to spawn the root process * and start geting into uspace diff --git a/lunaix-os/kernel/time/clock.c b/lunaix-os/kernel/time/clock.c index 3170731..a5b9dd8 100644 --- a/lunaix-os/kernel/time/clock.c +++ b/lunaix-os/kernel/time/clock.c @@ -19,12 +19,8 @@ __clock_read_datetime(struct twimap* map) clock_walltime(&dt); twimap_printf(map, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d", - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second); + dt.year, dt.month, dt.day, + dt.hour, dt.minute, dt.second); } void @@ -78,20 +74,5 @@ clock_systime() void clock_walltime(datetime_t* datetime) { - sysrtc->get_walltime(sysrtc, datetime); -} - -void -clock_init() -{ - int idx = 0; - struct device_def* pos; - foreach_exported_device_of(load_timedev, idx, pos) - { - if (pos->class.device != DEV_RTC) { - continue; - } - - pos->init(pos); - } + sysrtc->ops->get_walltime(sysrtc, datetime); } \ No newline at end of file diff --git a/lunaix-os/kernel/time/timer.c b/lunaix-os/kernel/time/timer.c index b9d98af..12c8e7f 100644 --- a/lunaix-os/kernel/time/timer.c +++ b/lunaix-os/kernel/time/timer.c @@ -25,7 +25,7 @@ LOG_MODULE("TIMER"); static void timer_update(); -static volatile struct lx_timer_context* timer_ctx = NULL; +static DEFINE_LLIST(timers); static volatile u32_t sched_ticks = 0; static volatile u32_t sched_ticks_counter = 0; @@ -36,13 +36,6 @@ void timer_init_context() { timer_pile = cake_new_pile("timer", sizeof(struct lx_timer), 1, 0); - timer_ctx = - (struct lx_timer_context*)valloc(sizeof(struct lx_timer_context)); - - assert_msg(timer_ctx, "Fail to initialize timer contex"); - - timer_ctx->active_timers = (struct lx_timer*)cake_grab(timer_pile); - llist_init_head(&timer_ctx->active_timers->link); } void @@ -52,8 +45,6 @@ timer_init() hwtimer_init(SYS_TIMER_FREQUENCY_HZ, timer_update); - timer_ctx->base_frequency = hwtimer_base_frequency(); - sched_ticks = (SYS_TIMER_FREQUENCY_HZ * SCHED_TIME_SLICE) / 1000; sched_ticks_counter = 0; } @@ -92,7 +83,7 @@ timer_run(ticks_t ticks, void (*callback)(void*), void* payload, u8_t flags) timer->payload = payload; timer->flags = flags; - llist_append(&timer_ctx->active_timers->link, &timer->link); + llist_append(&timers, &timer->link); return timer; } @@ -101,9 +92,8 @@ static void timer_update() { struct lx_timer *pos, *n; - struct lx_timer* timer_list_head = timer_ctx->active_timers; - llist_for_each(pos, n, &timer_list_head->link, link) + llist_for_each(pos, n, &timers, link) { if (--(pos->counter)) { continue; @@ -127,9 +117,3 @@ timer_update() schedule(); } } - -struct lx_timer_context* -timer_context() -{ - return (struct lx_timer_context*)timer_ctx; -} \ No newline at end of file diff --git a/lunaix-os/libs/crc.c b/lunaix-os/libs/crc.c index 71fa03e..c721023 100644 --- a/lunaix-os/libs/crc.c +++ b/lunaix-os/libs/crc.c @@ -55,7 +55,7 @@ static const unsigned int crc32_tab[] = { * @param size * @return unsigned int */ -unsigned int weak +unsigned int _weak crc32b(unsigned char* data, unsigned int size) { unsigned int crc = (unsigned int)-1, i = 0; diff --git a/lunaix-os/libs/hash.c b/lunaix-os/libs/hash.c index b4e5c6f..3a0555f 100644 --- a/lunaix-os/libs/hash.c +++ b/lunaix-os/libs/hash.c @@ -9,7 +9,7 @@ * @param str * @return unsigned int */ -u32_t weak +u32_t _weak strhash_32(const char* str, u32_t truncate_to) { if (!str) diff --git a/lunaix-os/libs/klibc/string/mem.c b/lunaix-os/libs/klibc/string/mem.c old mode 100755 new mode 100644 index b347b36..3e0ba08 --- a/lunaix-os/libs/klibc/string/mem.c +++ b/lunaix-os/libs/klibc/string/mem.c @@ -1,7 +1,7 @@ #include #include -void* weak +void* _weak memcpy(void* dest, const void* src, unsigned long num) { for (size_t i = 0; i < num; i++) { @@ -11,7 +11,7 @@ memcpy(void* dest, const void* src, unsigned long num) return dest; } -void* weak +void* _weak memmove(void* dest, const void* src, unsigned long num) { u8_t* dest_ptr = (u8_t*)dest; @@ -28,7 +28,7 @@ memmove(void* dest, const void* src, unsigned long num) return dest; } -void* weak +void* _weak memset(void* ptr, int value, unsigned long num) { for (size_t i = 0; i < num; i++) { @@ -38,7 +38,7 @@ memset(void* ptr, int value, unsigned long num) return ptr; } -int weak +int _weak memcmp(const void* ptr1, const void* ptr2, unsigned long num) { u8_t* p1 = (u8_t*)ptr1; diff --git a/lunaix-os/libs/klibc/string/strchr.c b/lunaix-os/libs/klibc/string/strchr.c index 3fdd7c3..353592d 100644 --- a/lunaix-os/libs/klibc/string/strchr.c +++ b/lunaix-os/libs/klibc/string/strchr.c @@ -1,7 +1,7 @@ #include #include -const char* weak +const char* _weak strchr(const char* str, int character) { char c = (char)character; diff --git a/lunaix-os/libs/klibc/string/strcmp.c b/lunaix-os/libs/klibc/string/strcmp.c index 072912b..4828287 100644 --- a/lunaix-os/libs/klibc/string/strcmp.c +++ b/lunaix-os/libs/klibc/string/strcmp.c @@ -1,7 +1,7 @@ #include #include -int weak +int _weak streq(const char* a, const char* b) { while (*a == *b) { diff --git a/lunaix-os/libs/klibc/string/strcpy.c b/lunaix-os/libs/klibc/string/strcpy.c index 4002d5b..7a3b430 100644 --- a/lunaix-os/libs/klibc/string/strcpy.c +++ b/lunaix-os/libs/klibc/string/strcpy.c @@ -1,7 +1,7 @@ #include #include -char* weak +char* _weak strcpy(char* dest, const char* src) { char c; @@ -24,7 +24,7 @@ strcpy(char* dest, const char* src) * @param n * @return char* */ -char* weak +char* _weak strncpy(char* dest, const char* src, unsigned long n) { char c; diff --git a/lunaix-os/libs/klibc/string/strlen.c b/lunaix-os/libs/klibc/string/strlen.c index 5e09423..134625e 100644 --- a/lunaix-os/libs/klibc/string/strlen.c +++ b/lunaix-os/libs/klibc/string/strlen.c @@ -1,7 +1,7 @@ #include #include -unsigned long weak +unsigned long _weak strlen(const char *str) { unsigned long len = 0; @@ -10,7 +10,7 @@ strlen(const char *str) return len; } -unsigned long weak +unsigned long _weak strnlen(const char *str, unsigned long max_len) { unsigned long len = 0; diff --git a/lunaix-os/libs/klibc/string/trim.c b/lunaix-os/libs/klibc/string/trim.c index 3c3d11a..82fbacc 100644 --- a/lunaix-os/libs/klibc/string/trim.c +++ b/lunaix-os/libs/klibc/string/trim.c @@ -4,7 +4,7 @@ #define WS_CHAR(c) \ (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r') -void weak +void _weak strrtrim(char* str) { unsigned long l = strlen(str); @@ -19,7 +19,7 @@ strrtrim(char* str) str[l + 1] = '\0'; } -char* weak +char* _weak strltrim_safe(char* str) { unsigned long l = 0; diff --git a/lunaix-os/link/lga.ldx b/lunaix-os/link/lga.ldx index 91e574d..76e99b4 100644 --- a/lunaix-os/link/lga.ldx +++ b/lunaix-os/link/lga.ldx @@ -44,31 +44,31 @@ . = ALIGN(8); - PROVIDE(__lga_dev_ld_timedev_start = .); + PROVIDE(__lga_dev_ld_post_start = .); - KEEP(*(.lga.devdefs.ld_timedev)); + KEEP(*(.lga.devdefs.ld_post)); - PROVIDE(__lga_dev_ld_timedev_end = .); + PROVIDE(__lga_dev_ld_post_end = .); /* ---- */ . = ALIGN(8); - PROVIDE(__lga_dev_ld_post_start = .); + PROVIDE(__lga_fs_start = .); - KEEP(*(.lga.devdefs.ld_post)); + KEEP(*(.lga.fs)); - PROVIDE(__lga_dev_ld_post_end = .); + PROVIDE(__lga_fs_end = .); /* ---- */ . = ALIGN(8); - PROVIDE(__lga_fs_start = .); + PROVIDE(__lga_lunainit_on_sysconf_start = .); - KEEP(*(.lga.fs)); + KEEP(*(.lga.lunainit.c_sysconf)); - PROVIDE(__lga_fs_end = .); + PROVIDE(__lga_lunainit_on_sysconf_end = .); /* ---- */ diff --git a/lunaix-os/live_debug.sh b/lunaix-os/live_debug.sh index 71da335..d70c54d 100755 --- a/lunaix-os/live_debug.sh +++ b/lunaix-os/live_debug.sh @@ -4,7 +4,7 @@ hmp_port=45454 gdb_port=1234 default_cmd="console=/dev/ttyS0" -make CMDLINE=${default_cmd} ARCH=${ARCH} MODE=${MODE:-debug} all -j5 || exit -1 +make ARCH=${ARCH} MODE=${MODE:-debug} all -j5 || exit -1 ./scripts/qemu.py \ scripts/qemus/qemu_x86_dev.json \ diff --git a/lunaix-os/makefile b/lunaix-os/makefile index 5b339d6..1fcb3cc 100644 --- a/lunaix-os/makefile +++ b/lunaix-os/makefile @@ -48,7 +48,6 @@ tool: @$(MAKE) $(MKFLAGS) -C scripts all -I $(mkinc_dir) .NOTPARALLEL: -export KCMD=$(CMDLINE) export LBUILD ARCH MODE all: $(kbuild_dir) tool kernel diff --git a/lunaix-os/makeinc/toolchain.mkinc b/lunaix-os/makeinc/toolchain.mkinc index 96dd3c4..246b9d1 100644 --- a/lunaix-os/makeinc/toolchain.mkinc +++ b/lunaix-os/makeinc/toolchain.mkinc @@ -14,7 +14,8 @@ W := -Wall -Wextra -Werror \ -Wno-discarded-qualifiers\ -Werror=incompatible-pointer-types -OFLAGS := -fno-omit-frame-pointer +OFLAGS := -fno-omit-frame-pointer \ + -finline-small-functions CFLAGS := -std=gnu99 $(OFLAGS) $(W) -g -- 2.27.0