rewrite the device subsystem interfaces (#48)
authorLunaixsky <lunaixsky@qq.com>
Wed, 20 Nov 2024 00:49:12 +0000 (00:49 +0000)
committerGitHub <noreply@github.com>
Wed, 20 Nov 2024 00:49:12 +0000 (00:49 +0000)
* 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

83 files changed:
lunaix-os/arch/generic/arch.c
lunaix-os/arch/generic/includes/asm-generic/isrm.h
lunaix-os/arch/x86/arch.c
lunaix-os/arch/x86/exceptions/isrm.c
lunaix-os/arch/x86/hal/apic_timer.c
lunaix-os/arch/x86/hal/mc146818a.c
lunaix-os/arch/x86/hal/ps2kbd.c
lunaix-os/arch/x86/hal/rngx86.c
lunaix-os/arch/x86/includes/asm/x86_isrm.h
lunaix-os/arch/x86/klib/fast_str.c
lunaix-os/hal/LBuild
lunaix-os/hal/acpi/acpi.c
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/ahci_pci.c
lunaix-os/hal/bus/pci.c
lunaix-os/hal/char/devnull.c
lunaix-os/hal/char/devzero.c
lunaix-os/hal/char/lxconsole.c
lunaix-os/hal/char/serial.c
lunaix-os/hal/char/uart/16x50_dev.c [new file with mode: 0644]
lunaix-os/hal/char/uart/16x50_isa.c
lunaix-os/hal/char/uart/16x50_pci.c
lunaix-os/hal/char/uart/LBuild
lunaix-os/hal/devtree/LBuild [new file with mode: 0644]
lunaix-os/hal/devtree/devtree.h
lunaix-os/hal/devtree/dt.c
lunaix-os/hal/devtree/dt_interrupt.c
lunaix-os/hal/devtree/dtm.c [new file with mode: 0644]
lunaix-os/hal/gfxa/gfxm.c
lunaix-os/hal/gfxa/vga/vga_pci.c
lunaix-os/hal/rtc/rtc_device.c
lunaix-os/hal/term/console.c
lunaix-os/hal/term/default_ops.c
lunaix-os/hal/term/term.c
lunaix-os/hal/term/term_io.c
lunaix-os/hal/timer/timer_device.c
lunaix-os/includes/hal/devtree.h
lunaix-os/includes/hal/devtreem.h [new file with mode: 0644]
lunaix-os/includes/hal/hwrtc.h
lunaix-os/includes/hal/hwtimer.h
lunaix-os/includes/hal/pci.h
lunaix-os/includes/hal/serial.h
lunaix-os/includes/hal/term.h
lunaix-os/includes/listings/changeling.lst [new file with mode: 0644]
lunaix-os/includes/listings/device_potens.lst [new file with mode: 0644]
lunaix-os/includes/listings/devnum.lst [new file with mode: 0644]
lunaix-os/includes/listings/devnum_fn.lst [new file with mode: 0644]
lunaix-os/includes/listings/devnum_vn.lst [new file with mode: 0644]
lunaix-os/includes/lunaix/changeling.h [new file with mode: 0644]
lunaix-os/includes/lunaix/clock.h
lunaix-os/includes/lunaix/compiler.h
lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/device_num.h
lunaix-os/includes/lunaix/ds/list.h [new file with mode: 0644]
lunaix-os/includes/lunaix/owloysius.h
lunaix-os/includes/lunaix/sections.h
lunaix-os/includes/lunaix/timer.h
lunaix-os/kernel/LBuild
lunaix-os/kernel/block/blkbuf.c
lunaix-os/kernel/changeling.c [new file with mode: 0644]
lunaix-os/kernel/device/LBuild
lunaix-os/kernel/device/capability.c [deleted file]
lunaix-os/kernel/device/devdb.c
lunaix-os/kernel/device/devfs.c
lunaix-os/kernel/device/device.c
lunaix-os/kernel/device/potentem.c [new file with mode: 0644]
lunaix-os/kernel/fs/mount.c
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/kinit.c
lunaix-os/kernel/time/clock.c
lunaix-os/kernel/time/timer.c
lunaix-os/libs/crc.c
lunaix-os/libs/hash.c
lunaix-os/libs/klibc/string/mem.c [changed mode: 0755->0644]
lunaix-os/libs/klibc/string/strchr.c
lunaix-os/libs/klibc/string/strcmp.c
lunaix-os/libs/klibc/string/strcpy.c
lunaix-os/libs/klibc/string/strlen.c
lunaix-os/libs/klibc/string/trim.c
lunaix-os/link/lga.ldx
lunaix-os/live_debug.sh
lunaix-os/makefile
lunaix-os/makeinc/toolchain.mkinc

index 3e62e7b996f4b637843adaf014eb451ddd57ef4b..609d641c3666f3f66ed914719a587fe370c3eec3 100644 (file)
@@ -1,8 +1,2 @@
 #include <hal/hwtimer.h>
 #include <lunaix/spike.h>
-
-_default struct hwtimer*
-select_platform_timer()
-{
-    fail("not implemented");
-}
\ No newline at end of file
index e8117bb4ed7f350e9c530a45b29adc259f9b1dd2..0bd4dda3f601c1df146f6a5d7b067b7931e7fbb6 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <lunaix/types.h>
 #include <lunaix/hart_state.h>
+#include <lunaix/device.h>
 
 #include <hal/devtree.h>
 
@@ -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
index f29b59840941128b9a5dd912d6691997f243e146..e98bdd9de7b3eca8b06085598b126d7c3f273270 100644 (file)
@@ -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()
 {
index a3c223d6833b3b52fd9d03c8b34d3e493574c5f4..fefc33e2dcfba4a0f074d4c0f6e608767d66873a 100644 (file)
@@ -1,5 +1,5 @@
 #include <lunaix/spike.h>
-#include <lunaix/owloysius.h>
+#include <lunaix/device.h>
 #include <asm/x86_isrm.h>
 
 #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
index 56cd41075e96a9663c8dd7b6b2b5a8197cb544e1..816fde3c93719b287e26d04a5a5a22bfb30d2c5e 100644 (file)
@@ -9,72 +9,45 @@
 #include <asm/x86_isrm.h>
 #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);
index 9c788f9b9ffa5984fc7043690129a66d9de8504b..f5bc285b2425a579c8eceb8eddf74621688530ea 100644 (file)
@@ -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
 
 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
index 02e98d1d8532afc8254fd5ba8be66c6d0a1f05a5..ee4a67e0f99855acb884cd8fc5b87fe386ddcea6 100644 (file)
@@ -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);
index c4441961c9ed83622d65fec0b679ec6d9b49c0c1..2baf96c50b3edf57ca019dd5ad8f5ff76a954b9c 100644 (file)
@@ -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
index a2bcacdaba354bca191cdc87265a01332fbe2cfd..b48608017342e060b2a83bbeac7c756ddd7afd6d 100644 (file)
@@ -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 */
index 27041785c30dc8b94e722a4b18bf934c8dccc466..d11ca1d66f95ef748ccd79409ec3934fdee12791 100644 (file)
@@ -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)
index f4ae4c96a7f3abbe1ba403293fd4ee72440e2af4..673a8fcdc7191102b0211ac38878a3585ab94628 100644 (file)
@@ -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
index bc90ba149e335940f5ae6a9ed81a2e3e33c9446f..b4faf630eb1f10d58d5602fd875ecebc91aa8018 100644 (file)
@@ -1,6 +1,6 @@
 #include <hal/acpi/acpi.h>
 
-#include <lunaix/device.h>
+#include <lunaix/owloysius.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
@@ -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
index f40ae2428a135457793da09bf209e42d271ab73c..04a71047b6708f4f06e8a3465a4900aead0acd88 100644 (file)
@@ -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
 
index 7c9288fa3b5b37b0677e6d1ae0005d76f8302a97..4435da12431ddc6a451f716664a02dcfcbf0c156 100644 (file)
@@ -1,30 +1,35 @@
 #include <lunaix/spike.h>
+#include <lunaix/status.h>
 
 #include <hal/ahci/ahci.h>
 #include <hal/pci.h>
 
 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(&param);
-    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
index 6b13b942e794db692649a8b89801d9ee77f15e89..3052a90eea05bc70b5128d41d96f90682ea6c218 100644 (file)
 
 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, &reg->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);
index 77650b0c922816192d6b72785e25124de754cb8b..3991548addec6dee0731677d412c00ca55f3fe19 100644 (file)
@@ -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);
index c637a34d0e3e4c49e654a06a6b2bf548631383cd..3eb9ea49d6855a1951e6a2891ee99952c65dca3b 100644 (file)
@@ -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);
index 4922297aaeead97009b739b29131155b3973cf4e..aa4136a65181c09ca474de4cc2119593baee1eab 100644 (file)
@@ -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
index d3d14c70eb66dbe13b1e0136aed677a0f4c0537d..7943bb3c36ab732ac897e0ad4fc6f0476afc72ab 100644 (file)
@@ -8,7 +8,6 @@
 #include <asm/pagetable.h>
 
 #include <hal/serial.h>
-#include <hal/term.h>
 
 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 (file)
index 0000000..326fede
--- /dev/null
@@ -0,0 +1,44 @@
+#include <lunaix/device.h>
+
+#include <hal/pci.h>
+
+#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
index 414dc334645ec3a63de6e279299066c024319066..39582236364660f4a1e21144eadf27a69ffd45ff 100644 (file)
@@ -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
index 59aac6c776dcc516f194bea19feb19f44f0a5a83..20beda12244206a04454e5e132c5b9cd18483d26 100644 (file)
@@ -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
index 83088c659775567aec63e6887517442122d9901f..9ed3119546bcc55d62d4224534141153c2c8b42b 100644 (file)
@@ -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 (file)
index 0000000..4709a35
--- /dev/null
@@ -0,0 +1,5 @@
+sources([
+    "dt_interrupt.c",
+    "dt.c",
+    "dtm.c"
+])
\ No newline at end of file
index 3b1df0803bb4c12d0530d98025d5f26eef07ef45..c2374c82820d05d2352b28e12d0038d8ab455432 100644 (file)
@@ -3,6 +3,44 @@
 
 #include <hal/devtree.h>
 
+#include <klibc/string.h>
+
+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);
 
index 72c443c340bc3026691145bdd6147dc6b3572bd4..f1d68608e5d883798aea4cc3c44f0e2a671b9c13 100644 (file)
@@ -1,12 +1,12 @@
 #include <lunaix/mm/valloc.h>
 #include <lunaix/syslog.h>
-
-#include <klibc/string.h>
+#include <lunaix/owloysius.h>
 
 #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
index e6ad3ca184ba2444a389e690c6fb2c7be28b049e..ab4d8b36dcf58e43f6d569cf30a6c3eea26cfdc9 100644 (file)
@@ -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 (file)
index 0000000..69ec2e5
--- /dev/null
@@ -0,0 +1,219 @@
+#include <hal/devtreem.h>
+#include <lunaix/device.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/syslog.h>
+#include <lunaix/owloysius.h>
+#include <lunaix/status.h>
+
+#include <klibc/string.h>
+
+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
index 27d1531d77f67a17b072bf24cbc9f481c946ac25..a58e88c0a2c3675b896a3758032d4d37656ecfab 100644 (file)
@@ -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)
index 1109e5a3f222415a2c72f511680eb6e82f77bd5c..af4f228d6472fd1b3dbf8e28943dcb54de1c83ff 100644 (file)
@@ -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
index ad063437c842de98fc7e1d8f75a695c71dd5f3e2..396c9bbf83c90684944bf3e9f7c8e4acfc2db066 100644 (file)
@@ -2,34 +2,51 @@
 #include <lunaix/fs/twimap.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/status.h>
+#include <lunaix/syslog.h>
 
 #include <hal/hwrtc.h>
 
-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);
     }
index 1c2a2cf83497d6fbb7521f5f551dacbd47042fac..ea479a31c7716e6356dfe2c1ec943629dc0ad7aa 100644 (file)
@@ -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);
     }
 
index fea8355409f606aaab0d58e1f3c1937366598069..ca0aa2c29976e8ed59fea7d241a64114ed88b71f 100644 (file)
@@ -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
index 4353265935e13a02479dd0ae3eaf339486467696..a71f93ca688089445cfc1d8b5ac77002153a2c29 100644 (file)
@@ -5,17 +5,22 @@
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
 #include <lunaix/status.h>
+#include <lunaix/syslog.h>
 
 #include <usr/lunaix/ioctl_defs.h>
 
+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
index 2c0fb66b3526a9a567ece59fe621c1f02cbffd63..03a9572dfb2fd4bbdc71ab4b7d5ec5772b701991 100644 (file)
@@ -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;
index 1db814764346acc7b03e56de810773a3f2cc8350..085f6bd95c36aebd787fbb8f877a28b849b52636 100644 (file)
@@ -3,26 +3,23 @@
 
 #include <hal/hwtimer.h>
 
-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
index 088e66f115d930d26b1e6d3853ec39aa19be2916..7b02ca5810a026c0942f4366b09c2e51f4ec8063 100644 (file)
@@ -6,6 +6,9 @@
 #include <lunaix/ds/hstr.h>
 #include <lunaix/ds/hashtable.h>
 #include <lunaix/boot_generic.h>
+#include <lunaix/changeling.h>
+
+#include <klibc/string.h>
 
 #define le(v) ((((v) >> 24) & 0x000000ff)  |\
                (((v) << 8)  & 0x00ff0000)  |\
 
 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 (file)
index 0000000..c8d10c2
--- /dev/null
@@ -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 <lunaix/ds/hashtable.h>
+#include <lunaix/ds/list.h>
+#include <klibc/hash.h>
+
+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 <lunaix/types.h>
+
+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 */
index c0186ff7cd14b363ba3b0b66d36347e0937d00d3..37a1877a1738a86fe55c56543d96fca2b7a32068 100644 (file)
@@ -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 */
index 2faa5076535d69155e0740290164d0087a1294fb..e7a22a7644fdfb7b7ff9e65eeb00159058fd5c45 100644 (file)
@@ -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 */
index 95ed7fd313eb0bc885507e2ca0ae290ca18b2d59..37815fefb8a41e71a12ce0981225dae5fc438128 100644 (file)
@@ -4,21 +4,12 @@
 #include <lunaix/device.h>
 #include <lunaix/ds/ldga.h>
 #include <lunaix/ds/llist.h>
+#include <lunaix/ds/hashtable.h>
 #include <lunaix/types.h>
+#include <lunaix/changeling.h>
 
 #include <asm-generic/isrm.h>
 
-#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);
index af345dad6d50ffa358d0449d696db48e91afdaed..ba2185c96ef35a1349e47b1844ba199624566c8b 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/ds/mutex.h>
 #include <lunaix/ds/waitq.h>
 #include <lunaix/ds/rbuffer.h>
+#include <hal/term.h>
 
 #include <usr/lunaix/serial.h>
 
@@ -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
index 407707e397c6fff6fa446f7fe7eee80b20167abc..be7abd0fdcda89163fb59139079e4b0299d2231f 100644 (file)
@@ -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 (file)
index 0000000..1e26576
--- /dev/null
@@ -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 (file)
index 0000000..9534b9a
--- /dev/null
@@ -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 (file)
index 0000000..81e5c1e
--- /dev/null
@@ -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 (file)
index 0000000..ad02c87
--- /dev/null
@@ -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 (file)
index 0000000..d898514
--- /dev/null
@@ -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 (file)
index 0000000..b9188ec
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef __LUNAIX_CHANGELING_H
+#define __LUNAIX_CHANGELING_H
+
+#include <lunaix/types.h>
+#include <lunaix/ds/llist.h>
+#include <lunaix/spike.h>
+#include <lunaix/ds/hstr.h>
+
+#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 <listings/changeling.lst>
+};
+
+/**
+ * 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 */
index 58e1ead7886ab1f7993e171bfd51d1c2422d1ec3..3cb1e4e5f6838398c0d04419bf74106ab3869f7f 100644 (file)
@@ -6,11 +6,8 @@
 #include <hal/hwrtc.h>
 #include <hal/hwtimer.h>
 
-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 */
index 178c0fedd598a91544d8cbaac81133942ba0430b..ffc73c885e33a7beba59d4a4c43e1be68cbffe1c 100644 (file)
@@ -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)
index 287cdadc6612db45ac35b0ae06fc2fa01dba4740..f1ce4d0df9a1bbfa19f4cc14cdf28f2875b74932 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __LUNAIX_DEVICE_H
 #define __LUNAIX_DEVICE_H
 
-#define DEVICE_NAME_SIZE 32
+#define DEVICE_NAME_SIZE 16
 
 #include <lunaix/device_num.h>
 #include <lunaix/ds/hashtable.h>
@@ -11,6 +11,9 @@
 #include <lunaix/ds/mutex.h>
 #include <lunaix/iopoll.h>
 #include <lunaix/types.h>
+#include <lunaix/changeling.h>
+
+#include <hal/devtreem.h>
 
 #include <usr/lunaix/device.h>
 
  */
 #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.
  * @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 <listings/device_potens.lst>
 };
 
+/**
+ * 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 */
index b59c857bae2205a37c3af28ca9c83f6e61c72559..eef79895b7c5bd987f8c21ab68fca7cf05250bb6 100644 (file)
 
 */
 
-#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 <listings/devnum_vn.lst>
+};
+
+enum devnum_fn
+{
+    dev_fn(NON),
+    #include <listings/devnum_fn.lst>
+};
+
+enum devnum
+{
+    dev_id(NON),
+    #include <listings/devnum.lst>
+};
 
 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 (file)
index 0000000..288ee66
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * @file slist.h
+ * @author Lunaixsky
+ * @brief This singly linked list is adopted from Linux kernel
+ * <linux/llist.h>
+ * @version 0.1
+ * @date 2022-03-12
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+#ifndef __LUNAIX_LIST_H
+#define __LUNAIX_LIST_H
+
+#include <lunaix/types.h>
+
+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 */
index 22311bb053b87424263fb11df42fcd70026b3d2d..99cffa262a01ba12b47a74eaaf13e4ac2c756664 100644 (file)
@@ -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
 
 /**
 
 #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 */
index 31828259f3edc667fe650f7e4d3f7eefcb3edd78..c164f0ce4ff6125b5268b6a7b1d3f1d76f5ea6af 100644 (file)
@@ -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)
index 08718adc474a1d8147476b739bb35be9b92d8fc4..fbbe2b78150c285898ce4f6d29926991481aab84 100644 (file)
@@ -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 */
index a71dd8bc7719b94d7b3515840669e5df98a15ba4..8e92773e54fba9df8055ca8b172a14a8b0348151 100644 (file)
@@ -16,6 +16,7 @@ sources([
     "lrud.c",
     "bcache.c",
     "syscall.c",
+    "changeling.c",
     "kprint/kp_records.c",
     "kprint/kprintf.c",
     "time/clock.c",
index 862a48e9c019c2491793b20cf4896a9d979340b7..bb29150477632511e5e0fcee5875f40c1439cd7e 100644 (file)
@@ -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 (file)
index 0000000..ff81597
--- /dev/null
@@ -0,0 +1,79 @@
+#include <lunaix/changeling.h>
+#include <lunaix/mm/valloc.h>
+
+#include <klibc/string.h>
+
+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
index c3c7255d82690b17cfa4ef77e6a3341239415c1c..989a81b1bdbeb2e38582b5b4595196ffa7794340 100644 (file)
@@ -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 (file)
index b31f914..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <lunaix/device.h>
-#include <lunaix/mm/valloc.h>
-
-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
index 09b6b5c006c7ff4f9853db22e0000fe09947cf19..a2483788069aef3f4ff8b209081df8a696c5b81b 100644 (file)
@@ -1,11 +1,14 @@
 #include <lunaix/device.h>
 #include <lunaix/fs/twifs.h>
 #include <lunaix/status.h>
+#include <lunaix/syslog.h>
 
 #include <klibc/hash.h>
 
 #include <klibc/strfmt.h>
 
+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 = "<unspecified>";
         }
 
+        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",
index 28f923ab411d2aad16cf7cc4eb862f4177d8f56d..c105f66a71bbed5072e6544de25b3bea75b9c27e 100644 (file)
@@ -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;
 }
 
index d32ca32bada4c093e47e728ec8a6836db9d22d22..9af8ac34fdd75b7b1a5545eacc4ed81967561493 100644 (file)
@@ -1,4 +1,3 @@
-
 #include <lunaix/device.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/twifs.h>
@@ -7,77 +6,61 @@
 #include <lunaix/spike.h>
 #include <lunaix/syscall.h>
 #include <lunaix/syscall_utils.h>
+#include <lunaix/owloysius.h>
 
 #include <klibc/strfmt.h>
 #include <klibc/string.h>
 
 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 (file)
index 0000000..b7de144
--- /dev/null
@@ -0,0 +1,33 @@
+#include <lunaix/device.h>
+#include <lunaix/mm/valloc.h>
+
+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
index 0f3b3fb7d42e807c22394ee354a5a342511f5ceb..c673e8418b6866541d8b413e68e5c72ea689806e 100644 (file)
@@ -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);
index 025fa3ff438ef8febaa8a8e48f9096bdf075fc4f..0eec6bf517cb53eb7aeab3972b7915897c95da1b 100644 (file)
@@ -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:
index 16c7976867e7da0252ec6fe3890a3d6245a3c95b..38804f2f58d0d63dfe665fc04d3989a93bdfbbe8 100644 (file)
@@ -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
index 3170731b842c340398227f33f898a61e2baf4060..a5b9dd838a6a04e119f3ef28a082d0ddec455d5e 100644 (file)
@@ -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
index b9d98afc8b79d7cb912f3f7092020e1e21a6ed32..12c8e7fea2d2a74e835dc4c76832cee6b7f2a481 100644 (file)
@@ -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
index 71fa03e55607af8aa1026835c5092629ee5cd502..c72102348d2327e5fd6e177af38f226a12833a99 100644 (file)
@@ -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;
index b4e5c6f58910f57545aaaf0d36f4cd07722e7c4e..3a0555fee81e38d2e58af2ad7a3ba0c800ff0d5e 100644 (file)
@@ -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)
old mode 100755 (executable)
new mode 100644 (file)
index b347b36..3e0ba08
@@ -1,7 +1,7 @@
 #include <klibc/string.h>
 #include <lunaix/types.h>
 
-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;
index 3fdd7c37c9d39d5b3e2e7a21788a84984f22d2ff..353592d9b9e0cf2bfa9c608dd94b0c502f872b8c 100644 (file)
@@ -1,7 +1,7 @@
 #include <klibc/string.h>
 #include <lunaix/types.h>
 
-const char* weak
+const char* _weak
 strchr(const char* str, int character)
 {
     char c = (char)character;
index 072912bcea7b0683bc6b443cc8728b8fe7bc1092..482828776d963e9b38de3dc31db8bfb7a3b3334e 100644 (file)
@@ -1,7 +1,7 @@
 #include <klibc/string.h>
 #include <lunaix/compiler.h>
 
-int weak
+int _weak
 streq(const char* a, const char* b)
 {
     while (*a == *b) {
index 4002d5b5e546acb788e26847e4122aa5a7a87467..7a3b430faad8a4cc673073ee752b7de6f099691c 100644 (file)
@@ -1,7 +1,7 @@
 #include <klibc/string.h>
 #include <lunaix/compiler.h>
 
-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;
index 5e09423811a7a9c3840a1ff9fff39bbf702755f6..134625e57394a6c2083af4bef10813be8c8642d5 100644 (file)
@@ -1,7 +1,7 @@
 #include <klibc/string.h>
 #include <lunaix/compiler.h>
 
-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;
index 3c3d11a7fc2f029998bfe2eca2716636f93c98fe..82fbacc8622b85b642fe414874af3738d82a3a29 100644 (file)
@@ -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;
index 91e574ddf5a3c742186bed066fbf03acc1b37663..76e99b4d5f440daf6c4feee03ea5f867ea907f4b 100644 (file)
 
     . = 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 = .);
 
     /* ---- */
 
index 71da3355cb25be1037d04beda140345b77301c1b..d70c54d39f39ad01856747d8437a5693f8175f04 100755 (executable)
@@ -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 \
index 5b339d6a47992feedea3b62570311767335b2b66..1fcb3cc2436ae39541363f148e674b75521119ee 100644 (file)
@@ -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
 
index 96dd3c4e1fcd308411a7437bdd5d911b8a320fb9..246b9d15196ff53d78a318494311f206a1b07d2c 100644 (file)
@@ -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