feat: device subsystem rework
authorMinep <lunaixsky@qq.com>
Mon, 28 Aug 2023 21:47:39 +0000 (22:47 +0100)
committerMinep <lunaixsky@qq.com>
Mon, 28 Aug 2023 21:51:51 +0000 (22:51 +0100)
      + dynamic device driver registration and discovery
      + centeralise the device managements
refactor: syslog

36 files changed:
lunaix-os/arch/i386/exceptions/i386_isrm.c
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/io_event.c
lunaix-os/hal/char/devnull.c [moved from lunaix-os/kernel/device/pseudo/devnull.c with 73% similarity]
lunaix-os/hal/char/ps2kbd.c
lunaix-os/hal/pci.c
lunaix-os/hal/rng/rngx86.c
lunaix-os/hal/rtc/hwrtc.c
lunaix-os/hal/rtc/mc146818a.c
lunaix-os/hal/timer/hwtimer.c
lunaix-os/includes/hal/pci.h
lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/device_num.h [new file with mode: 0644]
lunaix-os/includes/lunaix/ds/hashtable.h
lunaix-os/includes/lunaix/ds/ldga.h
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/isrm.h
lunaix-os/includes/lunaix/lxconsole.h
lunaix-os/includes/lunaix/syslog.h
lunaix-os/kernel/device/devdb.c [new file with mode: 0644]
lunaix-os/kernel/device/devfs.c
lunaix-os/kernel/device/device.c
lunaix-os/kernel/device/input.c
lunaix-os/kernel/device/pseudo/devpseudo.c [deleted file]
lunaix-os/kernel/fs/fs_setup.c [deleted file]
lunaix-os/kernel/fs/fsm.c
lunaix-os/kernel/fs/iso9660/mount.c
lunaix-os/kernel/fs/ramfs/ramfs.c
lunaix-os/kernel/fs/twifs/twifs.c
lunaix-os/kernel/kinit.c
lunaix-os/kernel/kprintf.c
lunaix-os/kernel/proc0.c
lunaix-os/kernel/process/taskfs.c
lunaix-os/kernel/time/clock.c
lunaix-os/kernel/tty/lxconsole.c
lunaix-os/link/linker.ld

index 2aabc39214711f8443c340301cc72ece00c0e53d..062853506cd9d4d14790d90603d3987e7808a9dc 100644 (file)
@@ -121,8 +121,9 @@ isrm_get(int iv)
 }
 
 ptr_t
-isrm_get_payload(int iv)
+isrm_get_payload(const isr_param* param)
 {
+    int iv = param->execp->vector;
     assert(iv < 256);
 
     return ivhand_payload[iv];
index 805976013d18e742adda46aa08e62bb311a2be1a..c20e21dffe9bb248ae7f6f5c043b5556c34bab43 100644 (file)
@@ -61,9 +61,6 @@ achi_register_ops(struct hba_port* port);
 void
 ahci_register_device(struct hba_device* hbadev);
 
-void*
-ahci_driver_init(struct pci_device* ahci_dev);
-
 void
 __hba_reset_port(hba_reg_t* port_reg)
 {
@@ -80,9 +77,11 @@ __hba_reset_port(hba_reg_t* port_reg)
     port_reg[HBA_RPxSCTL] &= ~0xf;
 }
 
-void*
-ahci_driver_init(struct pci_device* ahci_dev)
+int
+ahci_driver_init(struct device_def* def, struct device* dev)
 {
+    struct pci_device* ahci_dev = container_of(dev, struct pci_device, dev);
+
     struct pci_base_addr* bar6 = &ahci_dev->bar[5];
     assert_msg(bar6->type & BAR_TYPE_MMIO, "AHCI: BAR#6 is not MMIO.");
 
@@ -95,6 +94,7 @@ ahci_driver_init(struct pci_device* ahci_dev)
 
     int iv = isrm_ivexalloc(__ahci_hba_isr);
     pci_setup_msi(ahci_dev, iv);
+    isrm_set_payload(iv, (ptr_t)&ahcis);
 
     struct ahci_driver* ahci_drv = vzalloc(sizeof(*ahci_drv));
     struct ahci_hba* hba = &ahci_drv->hba;
@@ -197,9 +197,9 @@ ahci_driver_init(struct pci_device* ahci_dev)
         ahci_register_device(hbadev);
     }
 
-    return ahci_drv;
+    dev->underlay = ahci_drv;
+    return 0;
 }
-EXPORT_PCI_DEVICE(pci_ahci, AHCI_HBA_CLASS, 0, 0, ahci_driver_init);
 
 void
 ahci_register_device(struct hba_device* hbadev)
@@ -436,4 +436,14 @@ achi_register_ops(struct hba_port* port)
     } else {
         port->device->ops.submit = scsi_submit;
     }
-}
\ No newline at end of file
+}
+
+static struct pci_device_def ahcidef = {
+    .dev_class = AHCI_HBA_CLASS,
+    .dev_vendor = PCI_ID_ANY,
+    .dev_id = PCI_ID_ANY,
+    .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA, 0),
+                .name = "SATA AHCI",
+                .init_for = ahci_driver_init }
+};
+EXPORT_DEVICE(ahci, &ahcidef.devdef, load_on_demand);
\ No newline at end of file
index bb3142b37aefedc6749835460d61b6bba80a4afa..2ce49ef4e1c9701c8c2070436396e72dc7d0936d 100644 (file)
@@ -6,14 +6,14 @@
 
 LOG_MODULE("io_evt")
 
-extern struct llist_header ahcis;
-
 void
 __ahci_hba_isr(const isr_param* param)
 {
     struct ahci_hba* hba;
     struct ahci_driver *pos, *n;
-    llist_for_each(pos, n, &ahcis, ahci_drvs)
+    struct llist_header* ahcis = (struct llist_header*)isrm_get_payload(param);
+
+    llist_for_each(pos, n, ahcis, ahci_drvs)
     {
         if (pos->id == (int)param->execp->vector) {
             hba = &pos->hba;
similarity index 73%
rename from lunaix-os/kernel/device/pseudo/devnull.c
rename to lunaix-os/hal/char/devnull.c
index 3e82bba9c5e8afd5cb52e16798b2bfcda607feec..12bd00749b264b660b1c7ae4941a63753f4bfa25 100644 (file)
@@ -29,13 +29,21 @@ __null_rd(struct device* dev, void* buf, size_t offset, size_t len)
     return 0;
 }
 
-void
-pdev_nulldev_init()
+static int
+pdev_nulldev_init(struct device_def*)
 {
     struct device* devnull = device_addseq(NULL, NULL, "null");
     devnull->ops.write_page = __null_wr_pg;
     devnull->ops.write = __null_wr;
     devnull->ops.read_page = __null_rd_pg;
     devnull->ops.read = __null_rd;
+
+    return 0;
 }
-EXPORT_PSEUDODEV(nulldev, pdev_nulldev_init);
\ No newline at end of file
+
+static struct device_def devnull_def = {
+    .name = "null",
+    .class = DEVCLASS(DEVIF_NON, DEVFN_PSEUDO, 0, 0),
+    .init = pdev_nulldev_init
+};
+EXPORT_DEVICE(nulldev, &devnull_def, load_earlystage);
index 47c866d09ada47b39c664db04705f7c5c758c9b4..f59dcf30a35f96025e83954e68b5395a60b7d37c 100644 (file)
@@ -114,9 +114,6 @@ ps2_post_cmd(u8_t port, char cmd, u16_t arg);
 static void
 ps2_device_post_cmd(char cmd, char arg);
 
-static void
-ps2_kbd_init();
-
 static void
 ps2_process_cmd(void* arg);
 
@@ -215,8 +212,8 @@ ps2_device_post_cmd(char cmd, char arg)
     mutex_unlock(&cmd_q.mutex);
 }
 
-void
-ps2_kbd_init()
+static int
+ps2_kbd_init(struct device_def* devdef)
 {
 
     memset(&cmd_q, 0, sizeof(cmd_q));
@@ -281,14 +278,14 @@ ps2_kbd_init()
     result = ps2_issue_cmd_wretry(PS2_CMD_SELFTEST, PS2_NO_ARG);
     if (result != PS2_RESULT_TEST_OK) {
         kprintf(KWARN "controller self-test failed. (%x)\n", result);
-        // goto done;
+        goto done;
     }
 
     // 5、设备自检(端口1自检,通常是我们的键盘)
     result = ps2_issue_cmd_wretry(PS2_CMD_SELFTEST_PORT1, PS2_NO_ARG);
     if (result != 0) {
         kprintf(KERROR "interface test on port 1 failed. (%x)\n", result);
-        // goto done;
+        goto done;
     }
 
     ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT2_DISABLE, PS2_NO_ARG);
@@ -321,8 +318,11 @@ ps2_kbd_init()
     isrm_bindirq(PC_AT_IRQ_KBD, intr_ps2_kbd_handler);
 
     cpu_enable_interrupt();
+    return 0;
+
+done:
+    return 1;
 }
-EXPORT_INPUT_DEV(i8042_keyboard, ps2_kbd_init);
 
 static void
 ps2_process_cmd(void* arg)
@@ -572,4 +572,11 @@ ps2_issue_dev_cmd(char cmd, u16_t arg)
         ;
 
     return port_rdbyte(PS2_PORT_ENC_CMDREG);
-}
\ No newline at end of file
+}
+
+static struct device_def devrtc_i8042kbd = {
+    .name = "ps2 keyboard",
+    .class = DEVCLASS(DEVIF_SOC, DEVFN_INPUT, DEV_X86LEGACY, 0),
+    .init = ps2_kbd_init
+};
+EXPORT_DEVICE(i8042_kbd, &devrtc_i8042kbd, load_timerstage);
index 1457aa17e0d16b0fa1f97cdf1dfe1a2632390be6..9ac45d5ca680a266d429dc3203a188035acea78a 100644 (file)
 LOG_MODULE("PCI")
 
 static DEFINE_LLIST(pci_devices);
-static DEFINE_LLIST(pci_drivers);
 
 void
 pci_probe_msi_info(struct pci_device* device);
 
+static struct pci_device*
+pci_create_device(ptr_t pci_base, int devinfo)
+{
+    pci_reg_t class = pci_read_cspace(pci_base, 0x8);
+    struct hbucket* bucket = device_definitions_byif(DEVIF_PCI);
+
+    u32_t devid = PCI_DEV_DEVID(devinfo);
+    u32_t vendor = PCI_DEV_VENDOR(devinfo);
+
+    kappendf(".%x:%x, ", vendor, devid);
+
+    struct pci_device_def *pos, *n;
+    hashtable_bucket_foreach(bucket, pos, n, devdef.hlist_if)
+    {
+        if (pos->dev_class != PCI_DEV_CLASS(class)) {
+            continue;
+        }
+
+        int result = (pos->dev_vendor & vendor) == vendor &&
+                     (pos->dev_id & devid) == devid;
+
+        if (result) {
+            goto found;
+        }
+    }
+
+    kappendf(KWARN "unknown device\n");
+
+    return NULL;
+
+found:
+    pci_reg_t intr = pci_read_cspace(pci_base, 0x3c);
+
+    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;
+
+    device_prepare(&device->dev);
+
+    pci_probe_msi_info(device);
+    pci_probe_bar_info(device);
+
+    kappendf("%s (dev.%x:%x:%x) \n",
+             pos->devdef.name,
+             pos->devdef.class.meta,
+             pos->devdef.class.device,
+             pos->devdef.class.variant);
+
+    if (!pos->devdef.init_for) {
+        kappendf(KERROR "bad def\n");
+        goto fail;
+    }
+
+    int errno = pos->devdef.init_for(&pos->devdef, &device->dev);
+    if (errno) {
+        kappendf(KERROR "failed (e=%d)\n", errno);
+        goto fail;
+    }
+
+    llist_append(&pci_devices, &device->dev_chain);
+
+    return device;
+
+fail:
+    vfree(device);
+    return NULL;
+}
+
 void
 pci_probe_device(int bus, int dev, int funct)
 {
@@ -55,43 +124,14 @@ pci_probe_device(int bus, int dev, int funct)
         return;
     }
 
-    pci_reg_t intr = pci_read_cspace(base, 0x3c);
-    pci_reg_t class = pci_read_cspace(base, 0x8);
-
-    struct pci_device* device = vzalloc(sizeof(struct pci_device));
-    *device = (struct pci_device){ .cspace_base = base,
-                                   .class_info = class,
-                                   .device_info = reg1,
-                                   .intr_info = intr };
-
-    pci_probe_msi_info(device);
-    pci_probe_bar_info(device);
-
-    llist_append(&pci_devices, &device->dev_chain);
+    kprintf("pci.%d:%d:%d", bus, dev, funct);
 
-    if (!pci_bind_driver(device)) {
-        kprintf(KWARN "dev.%d:%d:%d %x:%x unknown device\n",
-                bus,
-                dev,
-                funct,
-                PCI_DEV_VENDOR(reg1),
-                PCI_DEV_DEVID(reg1));
-    } else {
-        kprintf("dev.%d:%d:%d %x:%x %s\n",
-                bus,
-                dev,
-                funct,
-                PCI_DEV_VENDOR(reg1),
-                PCI_DEV_DEVID(reg1),
-                device->driver.type->name);
-    }
+    pci_create_device(base, reg1);
 }
 
 void
-pci_probe()
+pci_scan()
 {
-    // 暴力扫描所有PCI设备
-    // XXX: 尽管最多会有256条PCI总线,但就目前而言,只考虑bus #0就足够了
     for (int bus = 0; bus < 256; bus++) {
         for (int dev = 0; dev < 32; dev++) {
             pci_probe_device(bus, dev, 0);
@@ -145,6 +185,55 @@ pci_probe_msi_info(struct pci_device* device)
     }
 }
 
+size_t
+pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num)
+{
+    pci_reg_t bar = pci_read_cspace(dev->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;
+    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);
+    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;
+}
+
 static void
 __pci_read_cspace(struct twimap* map)
 {
@@ -158,6 +247,8 @@ __pci_read_cspace(struct twimap* map)
     map->size_acc = 256;
 }
 
+/*---------- TwiFS interface definition ----------*/
+
 static void
 __pci_read_revid(struct twimap* map)
 {
@@ -242,106 +333,19 @@ pci_build_fsmapping()
 }
 EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping);
 
-size_t
-pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num)
-{
-    pci_reg_t bar = pci_read_cspace(dev->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;
-    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);
-    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;
-        }
-    }
+/*---------- PCI 3.0 HBA device definition ----------*/
 
-    return NULL;
-}
-
-void
-pci_add_driver(const char* name,
-               u32_t class,
-               u32_t vendor,
-               u32_t devid,
-               pci_drv_init init)
+static int
+pci_load_devices(struct device_def* def)
 {
-    struct pci_driver* pci_drv = valloc(sizeof(*pci_drv));
-    *pci_drv = (struct pci_driver){ .create_driver = init,
-                                    .dev_info = (vendor << 16) | devid,
-                                    .dev_class = class };
-    if (name) {
-        strncpy(pci_drv->name, name, PCI_DRV_NAME_LEN);
-    }
-
-    llist_append(&pci_drivers, &pci_drv->drivers);
-}
+    pci_scan();
 
-int
-pci_bind_driver(struct pci_device* pci_dev)
-{
-    struct pci_driver *pos, *n;
-    llist_for_each(pos, n, &pci_drivers, drivers)
-    {
-        if (pos->dev_info) {
-            if (pos->dev_info == pci_dev->device_info) {
-                goto check_type;
-            }
-            continue;
-        }
-    check_type:
-        if (pos->dev_class) {
-            if (pos->dev_class == PCI_DEV_CLASS(pci_dev->class_info)) {
-                pci_dev->driver.type = pos;
-                pci_dev->driver.instance = pos->create_driver(pci_dev);
-                return 1;
-            }
-        }
-    }
     return 0;
 }
 
-void
-pci_load_devices()
-{
-    int i = 0;
-    struct pci_driver* dev;
-    ldga_foreach(pci_dev_drivers, struct pci_driver*, i, dev)
-    {
-        llist_append(&pci_drivers, &dev->drivers);
-    }
-
-    pci_probe();
-}
\ No newline at end of file
+static struct device_def pci_def = {
+    .name = "pci3.0-hba",
+    .class = DEVCLASS(DEVIF_SOC, DEVFN_BUSIF, DEV_BUS, 0),
+    .init = pci_load_devices
+};
+EXPORT_DEVICE(pci3hba, &pci_def, load_poststage);
index aea9b691cd7b6e7a169890cd33a1c7baba0f2c19..bb069d7f61d13025f05ad19a05abd248e360b343 100644 (file)
@@ -28,11 +28,19 @@ __rand_rd(struct device* dev, void* buf, size_t offset, size_t len)
     return len;
 }
 
-void
-pdev_randdev_init()
+int
+pdev_randdev_init(struct device_def* devdef)
 {
     struct device* devrand = device_addseq(NULL, NULL, "rand");
     devrand->ops.read = __rand_rd;
     devrand->ops.read_page = __rand_rd_pg;
+
+    return 0;
 }
-EXPORT_PSEUDODEV(randdev, pdev_randdev_init);
\ No newline at end of file
+
+static struct device_def devrandx86_def = {
+    .name = "null",
+    .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_RNG, 0),
+    .init = pdev_randdev_init
+};
+EXPORT_DEVICE(randdev, &devrandx86_def, load_earlystage);
\ No newline at end of file
index c3fc1977fdb806bbd63ea33b87b42ccb7e901c87..5a53664214da108e4435a917fa8598b3640a620b 100644 (file)
@@ -12,16 +12,11 @@ static int rtc_count = 0;
 
 DEFINE_LLIST(rtcs);
 
-void
-hwrtc_init()
-{
-    ptr_t init;
-    int index;
-    ldga_foreach(rtcdev, ptr_t, index, init)
-    {
-        ((void (*)())init)();
-    }
-}
+// void
+// hwrtc_init()
+// {
+//     ldga_invoke_fn0(rtcdev);
+// }
 
 void
 hwrtc_walltime(datetime_t* dt)
index 1a507653192df1d5a5d40cdba38a89b3a6718955..e918ffdba83024aa0a578b608d62b3c0fea2b0fc 100644 (file)
@@ -145,8 +145,7 @@ mc146818_check_support(struct hwrtc* rtc)
 static void
 __rtc_tick(const isr_param* param)
 {
-    struct mc146818* state =
-      (struct mc146818*)isrm_get_payload(param->execp->vector);
+    struct mc146818* state = (struct mc146818*)isrm_get_payload(param);
 
     state->tick_counts++;
 
@@ -183,8 +182,8 @@ rtc_getcnt(struct hwrtc* rtc)
     return state->tick_counts;
 }
 
-static void
-rtc_init()
+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;
@@ -212,5 +211,13 @@ rtc_init()
     rtc->cls_mask = rtc_cls_mask;
     rtc->get_counts = rtc_getcnt;
     rtc->chfreq = rtc_chfreq;
+
+    return 0;
 }
-EXPORT_RTC_DEVICE(mc146818, rtc_init);
\ No newline at end of file
+
+static struct device_def devrtc_mc146818 = {
+    .name = "rtc_mc146818",
+    .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC, 1),
+    .init = rtc_init
+};
+EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_earlystage);
\ No newline at end of file
index 3a79ca1a7ec6d773521e8f8b7ff321b04526d406..1a994f7d3d163dcce4abaec3c9d5d530f3875bf1 100644 (file)
@@ -8,18 +8,21 @@ struct hwtimer* current_timer;
 ticks_t
 hwtimer_base_frequency()
 {
+    assert(current_timer);
     return current_timer->base_freq;
 }
 
 ticks_t
 hwtimer_current_systicks()
 {
+    assert(current_timer);
     return current_timer->systicks();
 }
 
 ticks_t
 hwtimer_to_ticks(u32_t value, int unit)
 {
+    assert(current_timer);
     // in case system frequency is less than 1000Hz
     if (unit != TIME_MS) {
         return current_timer->running_freq * unit * value;
index 2cc45b2a77348affaae369fdda855ce36d568c6a..186c6773aadfadafc16875319817e4b4232fc601 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LUNAIX_PCI_H
 #define __LUNAIX_PCI_H
 
+#include <lunaix/device.h>
 #include <lunaix/ds/ldga.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/types.h>
@@ -16,7 +17,7 @@
 #define PCI_REG_BAR(num) (0x10 + (num - 1) * 4)
 
 #define PCI_DEV_VENDOR(x) ((x)&0xffff)
-#define PCI_DEV_DEVID(x) ((x) >> 16)
+#define PCI_DEV_DEVID(x) (((x)&0xffff0000) >> 16)
 #define PCI_INTR_IRQ(x) ((x)&0xff)
 #define PCI_INTR_PIN(x) (((x)&0xff00) >> 8)
 #define PCI_DEV_CLASS(x) ((x) >> 8)
@@ -49,6 +50,8 @@
     (((bus)&0xff) << 16) | (((dev)&0xff) << 11) | (((funct)&0xff) << 8) |      \
       0x80000000
 
+#define PCI_ID_ANY (-1)
+
 typedef unsigned int pci_reg_t;
 
 // PCI device header format
@@ -58,16 +61,6 @@ typedef unsigned int pci_reg_t;
 #define BAR_TYPE_CACHABLE 0x2
 #define PCI_DRV_NAME_LEN 32
 
-#define EXPORT_PCI_DEVICE(name_, class, vendor_id, dev_id, init_fn)            \
-    static struct pci_driver pcidev_##name_ =                                  \
-      (struct pci_driver){ .name = #name_,                                     \
-                           .create_driver = (init_fn),                         \
-                           .dev_info = ((vendor_id) << 16) | (dev_id),         \
-                           .dev_class = (class) };                             \
-    export_ldga_el(pci_dev_drivers, name_, ptr_t, &pcidev_##name_)
-
-struct pci_driver;
-
 struct pci_base_addr
 {
     u32_t start;
@@ -77,39 +70,26 @@ struct pci_base_addr
 
 struct pci_device
 {
+    struct device dev;
     struct llist_header dev_chain;
     u32_t device_info;
     u32_t class_info;
     u32_t cspace_base;
     u32_t msi_loc;
     u16_t intr_info;
-    struct
-    {
-        struct pci_driver* type;
-        void* instance;
-    } driver;
     struct pci_base_addr bar[6];
 };
 
 typedef void* (*pci_drv_init)(struct pci_device*);
 
-struct pci_driver
+struct pci_device_def
 {
-    struct llist_header drivers;
-    u32_t dev_info;
     u32_t dev_class;
-    pci_drv_init create_driver;
-    char name[PCI_DRV_NAME_LEN];
+    u32_t dev_vendor;
+    u32_t dev_id;
+    struct device_def devdef;
 };
 
-/**
- * @brief 初始化PCI。这主要是通过扫描PCI总线进行拓扑重建。注意,该
- * 初始化不包括针对每个设备的初始化,因为那是设备驱动的事情。
- *
- */
-void
-pci_load_devices();
-
 /**
  * @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备
  * 类型代码请参阅: PCI LB Spec. Appendix D.
index 2634d81dcd076b22f752c1a981decbbb76c35034..52df8f0a0efcbde5c3fe6bf38d7e33d61ac207b9 100644 (file)
@@ -3,6 +3,8 @@
 
 #define DEVICE_NAME_SIZE 32
 
+#include <lunaix/device_num.h>
+#include <lunaix/ds/hashtable.h>
 #include <lunaix/ds/hstr.h>
 #include <lunaix/ds/ldga.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/types.h>
 
 /**
- * @brief Export pseudo device
+ * @brief Export a device definition
  *
  */
-#define EXPORT_PSEUDODEV(id, init_fn)                                          \
-    export_ldga_el(pseudo_dev, id, ptr_t, init_fn)
+#define EXPORT_DEVICE(id, devdef, load_order)                                  \
+    export_ldga_el(devdefs, id, ptr_t, devdef);                                \
+    export_ldga_el_sfx(devdefs, id##_ldorder, ptr_t, devdef, load_order);
+
+#define load_on_demand ld_ondemand
+
+/**
+ * @brief Mark the device definition should be loaded automatically as earlier
+ * as possible in the kernel bootstrapping stage (before initialization of file
+ * systems). Load here if your driver is standalone and require no other than
+ * basic memory allocation services
+ *
+ */
+#define load_earlystage ld_early
+
+/**
+ * @brief Mark the device definition should be loaded automatically after timer
+ * is ready. Load here if your driver require a basic timing service
+ *
+ */
+#define load_timerstage ld_aftertimer
+
+/**
+ * @brief Mark the device definition should be loaded automatically in
+ * the post boostrapping stage (i.e., the start up of proc0). Load here if your
+ * driver involves async mechanism
+ *
+ */
+#define load_poststage ld_post
+
+/**
+ * @brief Declare a device class
+ *
+ */
+#define DEVCLASS(devif, devfn, devkind, devvar)                                \
+    (struct devclass)                                                          \
+    {                                                                          \
+        .meta = DEV_META(devif, devfn), .device = (devkind),                   \
+        .variant = (devvar)                                                    \
+    }
 
 #define DEV_STRUCT_MAGIC 0x5645444c
 
 
 typedef unsigned int dev_t;
 
+struct devclass
+{
+    u32_t meta;
+    u32_t device;
+    u32_t variant;
+    u32_t hash;
+};
+
 struct device
 {
     u32_t magic;
@@ -36,6 +84,7 @@ struct device
     // TODO investigate event polling
 
     struct hstr name;
+    struct devclass class;
     dev_t dev_id;
     int dev_type;
     char name_val[DEVICE_NAME_SIZE];
@@ -51,12 +100,50 @@ struct device
     } ops;
 };
 
+struct device_def
+{
+    struct llist_header dev_list;
+    struct hlist_node hlist;
+    struct hlist_node hlist_if;
+    char* name;
+
+    struct devclass class;
+
+    int (*init)(struct device_def*);
+    int (*init_for)(struct device_def*, struct device*);
+};
+
+static inline u32_t devclass_hash(struct devclass class)
+{
+    return (((class.device & 0xffff) << 16) | (class.variant & 0xffff)) ^
+           ~class.meta;
+}
+
+void
+device_register_all();
+
+void
+device_prepare(struct device* dev);
+
+void
+device_setname(struct device* dev, char* fmt, ...);
+
+void
+device_setname(struct device* dev, char* fmt, ...);
+
+struct device*
+device_add_vargs(struct device* parent,
+                 void* underlay,
+                 char* name_fmt,
+                 u32_t type,
+                 va_list args);
+
 struct device*
 device_add(struct device* parent,
            void* underlay,
-           char* name_fmt,
            u32_t type,
-           va_list args);
+           char* name_fmt,
+           ...);
 
 struct device*
 device_addsys(struct device* parent, void* underlay, char* name_fmt, ...);
@@ -85,7 +172,27 @@ device_getbyname(struct device* root_dev, const char* name, size_t len);
 struct device*
 device_getbyoffset(struct device* root_dev, int pos);
 
+struct device*
+device_create_byclass(struct devclass* class,
+                      u32_t type,
+                      char* name,
+                      int* err_code);
+
+struct hbucket*
+device_definitions_byif(int if_type);
+
+void
+device_register_all();
+
+/*------ Load hooks ------*/
+
+void
+device_earlystage();
+
+void
+device_poststage();
+
 void
-device_install_pseudo();
+device_timerstage();
 
 #endif /* __LUNAIX_DEVICE_H */
diff --git a/lunaix-os/includes/lunaix/device_num.h b/lunaix-os/includes/lunaix/device_num.h
new file mode 100644 (file)
index 0000000..58e9122
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __LUNAIX_DEVICE_NUM_H
+#define __LUNAIX_DEVICE_NUM_H
+
+/*
+    Device metadata field (device_def::meta)
+
+    31          16 15           0
+    |  interface  |   function  |
+
+    Where the interface identify how the device is connected with the processor
+    Lunaix identify the following values:
+
+        NON: device do not have hardware interfacing
+
+        SOC: device conntected through some System-on-Chip interconnect bus
+            for example, southbridge on x86 platform, AMBA for ARM's series.
+
+        PCI: device connected through the peripheral component interconnect bus
+            (PCI)
+
+        USB: device connected through the universal serial bus (USB)
+
+        SPI: device connected through the serial peripheral interface (SPI)
+
+        I2C: device connected through the IIC protocol
+
+    The function defines the functionality that the device is designated to
+   serve. Lunaix identify the following values:
+
+        PSEDUO: a pseudo device which does not backed by any hardware. (e.g.
+                /dev/null)
+
+        CHAR: a character device, which support read/write and dealing with
+             characters. Backed hardware might exist.
+
+        SERIAL: a serial interface which talks
+
+        STORAGE: a device that is used for storage of data
+
+        INPUT: a device that accept external input.
+
+        TIME: a device that provides time related services, for example, timing
+             and clocking
+
+        BUSIF: a device that is the interface or HBAs for accessing interconnect
+   bus.
+
+        TTY: a device which can be called as teletypewriter, system can use such
+            device for output into external environment
+*/
+
+#define DEV_META(if_, function) (((if_)&0xffff) << 16) | ((function)&0xffff)
+#define DEV_IF(meta) ((meta) >> 16)
+#define DEV_FN(meta) (((meta)&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 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 DEV_BUILTIN 0x0
+#define DEV_X86LEGACY 0x1
+#define DEV_RNG 0x2
+#define DEV_RTC 0x3
+#define DEV_SATA 0x4
+#define DEV_NVME 0x5
+#define DEV_BUS 0x5
+
+#endif /* __LUNAIX_DEVICE_NUM_H */
index c3aea3f451dd973d19802009307aafa92e812e1f..41ca36b511d966fa591504525b2de6bfbd88b91b 100644 (file)
@@ -21,9 +21,9 @@ struct hbucket
     struct hlist_node* head;
 };
 
-#define __hashkey(table, hash) (hash % (sizeof(table) / sizeof(table[0])))
+#define __hashkey(table, hash) ((hash) % (sizeof(table) / sizeof(table[0])))
 
-#define DECLARE_HASHTABLE(name, bucket_num) struct hbucket name[bucket_num];
+#define DECLARE_HASHTABLE(name, bucket_num) struct hbucket name[(bucket_num)];
 
 #define hashtable_bucket_foreach(bucket, pos, n, member)                       \
     for (pos = list_entry((bucket)->head, typeof(*pos), member);               \
index c436798477775dafb5574d6121ad07c98c2a1150..8c00bbe12745d8c4e0eac421f13ee33a5f9d1979 100644 (file)
 
 #include <lunaix/types.h>
 
+#define ldga_el_id(ga_name, el_name) __lga_##ga_name##_##el_name
+#define ldga_section(ga_name) __attribute__((section(".lga." ga_name)))
+
 #define export_ldga_el(ga_name, el_name, type, val)                            \
-    type __attribute__((section(".lga." #ga_name)))                            \
-    __lga_##ga_name##_##el_name = (type)(val)
+    type ldga_section(#ga_name) ldga_el_id(ga_name, el_name) = (type)(val)
+
+#define export_ldga_el_sfx(ga_name, el_name, type, val, suffix)                \
+    type ldga_section(#ga_name "." #suffix) ldga_el_id(ga_name, el_name) =     \
+      (type)(val)
+
+#define export_ldga_el_idx(ga_name, i, type, val)                              \
+    export_ldga_el(ga_name, i, type, val)
+#define export_ldga_el_anon(ga_name, type, val)                                \
+    export_ldga_el_idx(ga_name, __COUNTER__, type, val)
 
 #define ldga_foreach(ga_name, el_type, index, el)                              \
     extern el_type __lga_##ga_name##_start[], __lga_##ga_name##_end;           \
          (ptr_t)&__lga_##ga_name##_end;                                        \
          el = __lga_##ga_name##_start[++index])
 
+/**
+ * @brief Invoke all elements in the array named `ga_name` of parameterless
+ * function pointers
+ *
+ */
+#define ldga_invoke_fn0(ga_name)                                               \
+    ({                                                                         \
+        int i = 0;                                                             \
+        ptr_t fn0;                                                             \
+        ldga_foreach(ga_name, ptr_t, i, fn0)                                   \
+        {                                                                      \
+            ((void (*)())fn0)();                                               \
+        }                                                                      \
+    })
+
 #endif /* __LUNAIX_LDGA_H */
index 5fbcc9083791607d8448cdaa53c7d1019cd90385..d90a773294099a40ef39ea90df2314aaabcc2c7d 100644 (file)
@@ -6,6 +6,7 @@
 #include <lunaix/ds/btrie.h>
 #include <lunaix/ds/hashtable.h>
 #include <lunaix/ds/hstr.h>
+#include <lunaix/ds/ldga.h>
 #include <lunaix/ds/llist.h>
 #include <lunaix/ds/lru.h>
 #include <lunaix/ds/mutex.h>
@@ -47,6 +48,9 @@
 
 #define TEST_FD(fd) (fd >= 0 && fd < VFS_MAX_FD)
 
+#define EXPORT_FILE_SYSTEM(fs_id, init_fn)                                        \
+    export_ldga_el(fs, fs_id, ptr_t, init_fn)
+
 #define VFS_VALID_CHAR(chr)                                                    \
     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
index e9f80b0027371be29e63577edad9c574ea849e81..160350a98d84eea3178124d053024c07c6fb30f9 100644 (file)
@@ -70,7 +70,7 @@ isr_cb
 isrm_get(int iv);
 
 ptr_t
-isrm_get_payload(int iv);
+isrm_get_payload(const isr_param*);
 
 void
 isrm_set_payload(int iv, ptr_t);
index 197bc9e55a9348c62f8703a96ee157af5b13f55b..fbf59a462d65568c71fa2708c74873a3d4b394fc 100644 (file)
@@ -11,9 +11,6 @@
 void
 lxconsole_init();
 
-void
-lxconsole_spawn_ttydev();
-
 void
 console_write_str(char* str);
 
index 464a133f889b89f90119f02e24f0e085eb50b545..eed1da22f065dda25c0963b6c0ce6ce52dfec8a5 100644 (file)
@@ -34,4 +34,7 @@ kprint_panic(const char* fmt, ...);
 void
 kprint_dbg(const char* fmt, ...);
 
+void
+kappendf(const char* fmt, ...);
+
 #endif /* __LUNAIX_SYSLOG_H */
diff --git a/lunaix-os/kernel/device/devdb.c b/lunaix-os/kernel/device/devdb.c
new file mode 100644 (file)
index 0000000..cf58a9d
--- /dev/null
@@ -0,0 +1,175 @@
+#include <lunaix/device.h>
+#include <lunaix/fs/twifs.h>
+#include <lunaix/status.h>
+
+#include <klibc/stdio.h>
+
+static DECLARE_HASHTABLE(dev_registry, 32);
+static DECLARE_HASHTABLE(dev_byif, 8);
+static DEFINE_LLIST(dev_registry_flat);
+
+static struct device* adhoc_devcat;
+
+void
+device_register_all()
+{
+    adhoc_devcat = device_addcat(NULL, "adhoc");
+
+    hashtable_init(dev_registry);
+    hashtable_init(dev_byif);
+
+    int idx = 0;
+    struct device_def* devdef;
+    ldga_foreach(devdefs, struct device_def*, idx, devdef)
+    {
+        u32_t hash = devclass_hash(devdef->class);
+        devdef->class.hash = hash;
+
+        hashtable_hash_in(dev_registry, &devdef->hlist, hash);
+        hashtable_hash_in(
+          dev_byif, &devdef->hlist_if, DEV_IF(devdef->class.meta));
+
+        llist_append(&dev_registry_flat, &devdef->dev_list);
+    }
+}
+
+static int
+devclass_eq(struct devclass* c1, struct devclass* c2)
+{
+    return c1->meta == c2->meta && c1->variant == c2->variant &&
+           c1->device == c2->device;
+}
+
+struct device_def*
+devdef_byclass(struct devclass* class)
+{
+    u32_t hash = devclass_hash(*class);
+    int errno;
+
+    struct device_def *pos, *n;
+    hashtable_hash_foreach(dev_registry, hash, pos, n, hlist)
+    {
+        if (pos->class.hash != hash) {
+            continue;
+        }
+        if (devclass_eq(class, &pos->class)) {
+            break;
+        }
+    }
+
+    return pos;
+}
+
+struct device*
+device_create_byclass(struct devclass* class,
+                      u32_t type,
+                      char* name,
+                      int* err_code)
+{
+    int errno;
+    struct device_def* devdef = devdef_byclass(class);
+
+    if (!devdef) {
+        *err_code = ENOENT;
+        return NULL;
+    }
+
+    if (!devdef->init_for) {
+        if (err_code) {
+            *err_code = ENOTSUP;
+        }
+        return NULL;
+    }
+
+    struct device* dev = device_add(adhoc_devcat, NULL, type, NULL);
+
+    errno = devdef->init_for(devdef, dev);
+    if (err_code && !errno) {
+        *err_code = errno;
+        device_remove(dev);
+        return NULL;
+    }
+
+    device_setname(dev,
+                   "%s_%d:%d:%d_%d",
+                   name,
+                   class->meta,
+                   class->device,
+                   class->device,
+                   dev->dev_id);
+
+    return dev;
+}
+
+struct hbucket*
+device_definitions_byif(int if_type)
+{
+    return &dev_byif[__hashkey(dev_byif, if_type)];
+}
+
+#define device_load_on_stage(stage)                                            \
+    ({                                                                         \
+        int idx = 0;                                                           \
+        struct device_def* devdef;                                             \
+        ldga_foreach(dev_ld_##stage, struct device_def*, idx, devdef)          \
+        {                                                                      \
+            devdef->init(devdef);                                              \
+        }                                                                      \
+    })
+
+void
+device_earlystage()
+{
+    device_load_on_stage(early);
+}
+
+void
+device_timerstage()
+{
+    device_load_on_stage(aftertimer);
+}
+
+void
+device_poststage()
+{
+    device_load_on_stage(post);
+}
+
+static int
+__devdb_db_gonext(struct twimap* mapping)
+{
+    struct device_def* current = twimap_index(mapping, struct device_def*);
+    if (current->dev_list.next == &dev_registry_flat) {
+        return 0;
+    }
+    mapping->index =
+      list_entry(current->dev_list.next, struct device_def, dev_list);
+    return 1;
+}
+
+static void
+__devdb_twifs_lsdb(struct twimap* mapping)
+{
+    char flags[32];
+    struct device_def* def = twimap_index(mapping, struct device_def*);
+
+    int meta = def->class.meta;
+    ksnprintf(flags, 32, "if=%x,fn=%x", DEV_IF(meta), DEV_FN(meta));
+
+    twimap_printf(mapping,
+                  "%d:%d:%d %s (%s)\n",
+                  def->class.meta,
+                  def->class.device,
+                  def->class.variant,
+                  def->name,
+                  flags);
+}
+
+static void
+devdb_twifs_plugin()
+{
+    struct twimap* map = twifs_mapping(NULL, NULL, "devtab");
+    map->read = __devdb_twifs_lsdb;
+    map->go_next = __devdb_db_gonext;
+}
+EXPORT_TWIFS_PLUGIN(devdb, devdb_twifs_plugin);
\ No newline at end of file
index 2951456ce54a681bf8c9149a878390ee5da3c170..fb55d2403b10dfdd70ea152d92ffdbd8e6d85123 100644 (file)
@@ -178,6 +178,7 @@ devfs_init()
     fs->mount = devfs_mount;
     fs->unmount = devfs_unmount;
 }
+EXPORT_FILE_SYSTEM(devfs, devfs_init);
 
 struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
                                        .open = default_inode_open,
index 979b461b86184a8c1bcdfa18f3ce0f0505f094a1..b794334628ca696d4f44f0f8ab15722ac5fa5aaa 100644 (file)
@@ -12,15 +12,48 @@ static DEFINE_LLIST(root_list);
 
 static volatile dev_t devid = 0;
 
+void
+device_prepare(struct device* dev)
+{
+    dev->magic = DEV_STRUCT_MAGIC;
+    dev->dev_id = devid++;
+
+    llist_init_head(&dev->children);
+}
+
+static void
+device_setname_vargs(struct device* dev, char* fmt, va_list args)
+{
+    size_t strlen =
+      __ksprintf_internal(dev->name_val, fmt, DEVICE_NAME_SIZE, args);
+
+    dev->name = HSTR(dev->name_val, strlen);
+
+    hstr_rehash(&dev->name, HSTR_FULL_HASH);
+}
+
+void
+device_setname(struct device* dev, char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    device_setname_vargs(dev, fmt, args);
+
+    va_end(args);
+}
+
 struct device*
-device_add(struct device* parent,
-           void* underlay,
-           char* name_fmt,
-           u32_t type,
-           va_list args)
+device_add_vargs(struct device* parent,
+                 void* underlay,
+                 char* name_fmt,
+                 u32_t type,
+                 va_list args)
 {
     struct device* dev = vzalloc(sizeof(struct device));
 
+    device_prepare(dev);
+
     if (parent) {
         assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
         llist_append(&parent->children, &dev->siblings);
@@ -28,19 +61,31 @@ device_add(struct device* parent,
         llist_append(&root_list, &dev->siblings);
     }
 
-    size_t strlen =
-      __ksprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
+    if (name_fmt) {
+        device_setname_vargs(dev, name_fmt, args);
+    }
 
-    dev->magic = DEV_STRUCT_MAGIC;
-    dev->dev_id = devid++;
-    dev->name = HSTR(dev->name_val, strlen);
     dev->parent = parent;
     dev->underlay = underlay;
     dev->dev_type = type;
 
-    hstr_rehash(&dev->name, HSTR_FULL_HASH);
-    llist_init_head(&dev->children);
+    return dev;
+}
 
+struct device*
+device_add(struct device* parent,
+           void* underlay,
+           u32_t type,
+           char* name_fmt,
+           ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      device_add_vargs(parent, underlay, name_fmt, type, args);
+
+    va_end(args);
     return dev;
 }
 
@@ -51,7 +96,7 @@ device_addsys(struct device* parent, void* underlay, char* name_fmt, ...)
     va_start(args, name_fmt);
 
     struct device* dev =
-      device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
+      device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, args);
 
     va_end(args);
     return dev;
@@ -64,7 +109,7 @@ device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
     va_start(args, name_fmt);
 
     struct device* dev =
-      device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
+      device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, args);
 
     va_end(args);
     return dev;
@@ -77,7 +122,7 @@ device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
     va_start(args, name_fmt);
 
     struct device* dev =
-      device_add(parent, underlay, name_fmt, DEV_IFVOL, args);
+      device_add_vargs(parent, underlay, name_fmt, DEV_IFVOL, args);
 
     va_end(args);
     return dev;
@@ -89,7 +134,8 @@ device_addcat(struct device* parent, char* name_fmt, ...)
     va_list args;
     va_start(args, name_fmt);
 
-    struct device* dev = device_add(parent, NULL, name_fmt, DEV_IFCAT, args);
+    struct device* dev =
+      device_add_vargs(parent, NULL, name_fmt, DEV_IFCAT, args);
 
     va_end(args);
     return dev;
index 0680fefebe7be56c4992f3a6dc06945325825902..52c8820400f31f8c06c28b1308eba0b21d5cfbbf 100644 (file)
@@ -15,13 +15,6 @@ void
 input_init()
 {
     input_devcat = device_addcat(NULL, "input");
-
-    int i;
-    ptr_t input_dev_init;
-    ldga_foreach(inputdev, ptr_t, i, input_dev_init)
-    {
-        ((void (*)())input_dev_init)();
-    }
 }
 
 void
@@ -88,7 +81,7 @@ input_add_device(char* name_fmt, ...)
     va_start(args, name_fmt);
 
     struct device* dev =
-      device_add(input_devcat, idev, name_fmt, DEV_IFSEQ, args);
+      device_add_vargs(input_devcat, idev, name_fmt, DEV_IFSEQ, args);
 
     idev->dev_if = dev;
     dev->ops.read = __input_dev_read;
diff --git a/lunaix-os/kernel/device/pseudo/devpseudo.c b/lunaix-os/kernel/device/pseudo/devpseudo.c
deleted file mode 100644 (file)
index 45ee4a4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <lunaix/device.h>
-
-extern void
-devbuiltin_init_rand();
-
-extern void
-devbuiltin_init_null();
-
-void
-device_install_pseudo()
-{
-    ptr_t pdev_init_fn;
-    int index;
-    ldga_foreach(pseudo_dev, ptr_t, index, pdev_init_fn)
-    {
-        ((void (*)())pdev_init_fn)();
-    }
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/fs/fs_setup.c b/lunaix-os/kernel/fs/fs_setup.c
deleted file mode 100644 (file)
index 0966222..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <lunaix/fs.h>
-#include <lunaix/fs/devfs.h>
-#include <lunaix/fs/iso9660.h>
-#include <lunaix/fs/ramfs.h>
-#include <lunaix/fs/taskfs.h>
-#include <lunaix/fs/twifs.h>
-
-void
-fsm_register_all()
-{
-    ramfs_init();
-    twifs_init();
-    devfs_init();
-    taskfs_init();
-    iso9660_init();
-
-    // ... more fs implementation
-}
\ No newline at end of file
index a6a2be69686ebda6005ba19f24152743653192d0..ca1221c095a0e063a6d3dd0c5dea16cbbe8a0232 100644 (file)
@@ -23,7 +23,7 @@ fsm_init()
 {
     hashtable_init(fs_registry);
 
-    fsm_register_all();
+    ldga_invoke_fn0(fs);
 }
 
 void
index 19895609567b4647c1ea204e1ae21883b41465cd..3849add82eb53117c60ae75655614b53cf60b6fa 100644 (file)
@@ -109,4 +109,5 @@ iso9660_init()
     fs->unmount = iso9660_unmount;
 
     fsm_register(fs);
-}
\ No newline at end of file
+}
+EXPORT_FILE_SYSTEM(iso9660, iso9660_init);
\ No newline at end of file
index fece9b3ba503a369445896c781b13d58d1ae1414..e2d1263607c2c8a79a596e7d2f40f00f0cb32938 100644 (file)
@@ -146,6 +146,7 @@ ramfs_init()
 
     fsm_register(ramfs);
 }
+EXPORT_FILE_SYSTEM(ramfs, ramfs_init);
 
 int
 ramfs_mksymlink(struct v_inode* this, const char* target)
index 729b5f770f7ea164d91f24d7b78e553433b1aa44..4d987ae8c25115f1653de0332c2e3e6e3a6d3634 100644 (file)
@@ -241,16 +241,12 @@ twifs_init()
 
     fs_root = twifs_dir_node(NULL, NULL, 0, 0);
 }
+EXPORT_FILE_SYSTEM(twifs, twifs_init);
 
 void
 twifs_register_plugins()
 {
-    int i = 0;
-    ptr_t init_twifs_plugin_fn;
-    ldga_foreach(twiplugin_inits, ptr_t, i, init_twifs_plugin_fn)
-    {
-        ((void (*)())init_twifs_plugin_fn)();
-    }
+    ldga_invoke_fn0(twiplugin_inits);
 }
 
 int
index 046054472f7b97d74005ca846c0efa5c41e30085..f5944b50a90b6e9cbdf16c0f147a04f1ede590bb 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <hal/acpi/acpi.h>
 #include <hal/intc.h>
-#include <hal/pci.h>
 
 #include <sys/abi.h>
 #include <sys/interrupts.h>
@@ -53,6 +52,8 @@ kernel_bootstrap(struct boot_handoff* bhctx)
     /* Prepare stack trace environment */
     trace_modksyms_init(bhctx);
 
+    device_register_all();
+
     // crt
     tty_init(ioremap(0xB8000, PG_SIZE));
     tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
@@ -68,11 +69,15 @@ kernel_bootstrap(struct boot_handoff* bhctx)
     /* Get intc online, this is the cornerstone when initing devices */
     intc_init();
 
+    input_init();
+    device_earlystage();
+
     /* System timing and clock support */
     clock_init();
     timer_init();
 
-    input_init();
+    device_timerstage();
+
     block_init();
 
     /* the bare metal are now happy, let's get software over with */
@@ -88,9 +93,6 @@ kernel_bootstrap(struct boot_handoff* bhctx)
     vfs_mount("/sys", "twifs", NULL, MNT_RO);
     vfs_mount("/task", "taskfs", NULL, MNT_RO);
 
-    lxconsole_spawn_ttydev();
-    device_install_pseudo();
-
     /* Finish up bootstrapping sequence, we are ready to spawn the root process
      * and start geting into uspace
      */
index 91646e9e51d281b4c50551180abce74de2dedaff..15c8c1400bb2387374365bcf940cc97f3b14d3d8 100644 (file)
@@ -8,62 +8,80 @@
 #define MAX_KPRINTF_BUF_SIZE 512
 #define MAX_XFMT_SIZE 512
 
+static char* log_prefix[] = { "- ", "W ", "E ", "D " };
+static char* color_code[] = { "", "\033[6;0m", "\033[12;0m", "\033[9;0m" };
+
 void
 __kprintf_internal(const char* component,
                    int log_level,
+                   const char* prefix,
                    const char* fmt,
                    va_list args)
 {
     char buf[MAX_KPRINTF_BUF_SIZE];
     char expanded_fmt[MAX_XFMT_SIZE];
-
-    switch (log_level) {
-        case 1:
-            // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12);
-            ksnprintf(expanded_fmt,
-                      MAX_XFMT_SIZE,
-                      "\033[6;0mW %s: %s\033[39;49m",
-                      component,
-                      fmt);
-            break;
-        case 2:
-            // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12);
-            ksnprintf(expanded_fmt,
-                      MAX_XFMT_SIZE,
-                      "\033[12;0mE %s: %s\033[39;49m",
-                      component,
-                      fmt);
-            break;
-        case 3:
-            // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12);
-            ksnprintf(expanded_fmt,
-                      MAX_XFMT_SIZE,
-                      "\033[9;0mD %s: %s\033[39;49m",
-                      component,
-                      fmt);
-            break;
-        default:
-            ksnprintf(expanded_fmt, MAX_XFMT_SIZE, "- %s: %s", component, fmt);
-            break;
+    char* color = color_code[log_level];
+
+    if (component) {
+        ksnprintf(expanded_fmt,
+                  MAX_XFMT_SIZE,
+                  "%s%s%s: %s\033[39;49m",
+                  color,
+                  prefix,
+                  component,
+                  fmt);
+    } else {
+        ksnprintf(
+          expanded_fmt, MAX_XFMT_SIZE, "%s%s%s\033[39;49m", color, prefix, fmt);
     }
 
     __ksprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args);
     console_write_str(buf);
 }
 
+char*
+__get_loglevel(char* fmt, int* log_level_out)
+{
+    char l = '0';
+    if (*fmt == '\x1b') {
+        l = *(++fmt);
+        fmt++;
+    }
+    l -= '0';
+
+    if (l > 3) {
+        l = 0;
+    }
+
+    *log_level_out = (int)l;
+    return fmt;
+}
+
+void
+kappendf(const char* fmt, ...)
+{
+    char buf[MAX_KPRINTF_BUF_SIZE];
+
+    va_list args;
+    va_start(args, fmt);
+
+    int log_level;
+    fmt = __get_loglevel(fmt, &log_level);
+
+    __kprintf_internal(NULL, log_level, "", fmt, args);
+
+    va_end(args);
+}
+
 void
 __kprintf(const char* component, const char* fmt, va_list args)
 {
     if (!fmt)
         return;
-    char log_level = '0';
 
-    if (*fmt == '\x1b') {
-        log_level = *(++fmt);
-        fmt++;
-    }
-
-    __kprintf_internal(component, log_level - '0', fmt, args);
+    int log_level;
+    fmt = __get_loglevel(fmt, &log_level);
+    __kprintf_internal(component, log_level, log_prefix[log_level], fmt, args);
 }
 
 void
@@ -80,6 +98,8 @@ kprint_panic(const char* fmt, ...)
     tty_put_str_at(buf, 0, 24);
 
     va_end(args);
+
+    spin();
 }
 
 void
@@ -128,5 +148,5 @@ kprint_hex(const void* buffer, unsigned int size)
 
 __DEFINE_LXSYSCALL3(void, syslog, int, level, const char*, fmt, va_list, args)
 {
-    __kprintf_internal("syslog", level, fmt, args);
+    __kprintf_internal("syslog", level, "", fmt, args);
 }
\ No newline at end of file
index c7501af0e733c0769a23cd95fd2267d0dbfe9bd5..4b430b5a15d801943b3244e9380b25768b6b82ee 100644 (file)
@@ -18,8 +18,6 @@
 
 #include <sdbg/protocol.h>
 
-#include <hal/pci.h>
-
 #include <klibc/string.h>
 
 LOG_MODULE("PROC0")
@@ -98,16 +96,14 @@ init_platform()
             __VERSION__,
             __TIME__);
 
+    device_poststage();
+
     twifs_register_plugins();
 
-    /*
-     * all device registering and loading must defered to here!
-     * due to limited stack size and partial scheduling context
-     */
-    pci_load_devices();
+    // FIXME This 8025 serial should integrated into device layer
+    serial_init();
 
     // debugger
-    serial_init();
     sdbg_init();
 
     // console
index 6ecdc8f5d1db17e95bf6d3899a4b9ef984cca22a..2aa1ed9f83f8c4253712c47d9e9dca5320485c9a 100644 (file)
@@ -226,4 +226,5 @@ taskfs_init()
     attr_export_table = vcalloc(ATTR_TABLE_LEN, sizeof(struct hbucket));
 
     export_task_attr();
-}
\ No newline at end of file
+}
+EXPORT_FILE_SYSTEM(taskfs, taskfs_init);
\ No newline at end of file
index be6b21ba3c61ed3a442345b7e32233f828d81498..ef557c784e8dd47895a4f1148874d9f1cd1e02aa 100644 (file)
@@ -54,7 +54,7 @@ EXPORT_TWIFS_PLUGIN(sys_clock, clock_build_mapping);
 void
 clock_init()
 {
-    hwrtc_init();
+    // hwrtc_init();
 }
 
 time_t
index 8d0747dda601c905c67a8ff4c863705ddd22a944..0bcb9b71213e015471405fcfee4dccffc4be1a80 100644 (file)
@@ -146,20 +146,6 @@ __tty_read_pg(struct device* dev, void* buf, size_t offset)
     return __tty_read(dev, buf, offset, PG_SIZE);
 }
 
-void
-lxconsole_spawn_ttydev()
-{
-    struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
-    tty_dev->ops.write = __tty_write;
-    tty_dev->ops.write_page = __tty_write_pg;
-    tty_dev->ops.read = __tty_read;
-    tty_dev->ops.read_page = __tty_read_pg;
-    tty_dev->ops.exec_cmd = __tty_exec_cmd;
-
-    waitq_init(&lx_reader);
-    input_add_listener(__lxconsole_listener);
-}
-
 int
 __tty_write(struct device* dev, void* buf, size_t offset, size_t len)
 {
@@ -352,4 +338,26 @@ console_start_flushing()
     struct lx_timer* timer =
       timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC);
     lx_console.flush_timer = timer;
-}
\ No newline at end of file
+}
+
+static int
+lxconsole_spawn_ttydev(struct device_def* devdef)
+{
+    struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
+    tty_dev->ops.write = __tty_write;
+    tty_dev->ops.write_page = __tty_write_pg;
+    tty_dev->ops.read = __tty_read;
+    tty_dev->ops.read_page = __tty_read_pg;
+    tty_dev->ops.exec_cmd = __tty_exec_cmd;
+
+    waitq_init(&lx_reader);
+    input_add_listener(__lxconsole_listener);
+
+    return 0;
+}
+
+static struct device_def lxconsole_def = {
+    .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN, 0),
+    .init = lxconsole_spawn_ttydev
+};
+EXPORT_DEVICE(lxconsole, &lxconsole_def, load_earlystage);
\ No newline at end of file
index 52ce3eb6c2d9147951751f3c9a4bfc37d7f045d0..1cc64bb2901a6d3f42b6a594fc33317eebd710dd 100644 (file)
@@ -70,41 +70,52 @@ SECTIONS {
         /* align to 8 bytes, so it can cover both 32 and 64 bits address line*/
         . = ALIGN(8);
 
-        PROVIDE(__lga_pci_dev_drivers_start = .);
+        PROVIDE(__lga_devdefs_start = .);
         
-        KEEP(*(.lga.pci_dev_drivers));
+        KEEP(*(.lga.devdefs));
 
-        PROVIDE(__lga_pci_dev_drivers_end = .);
+        PROVIDE(__lga_devdefs_end = .);
 
         /* ---- */
 
         . = ALIGN(8);
 
-        PROVIDE(__lga_rtcdev_start = .);
+        PROVIDE(__lga_dev_ld_early_start = .);
         
-        KEEP(*(.lga.rtcdev));
+        KEEP(*(.lga.devdefs.ld_early));
 
-        PROVIDE(__lga_rtcdev_end = .);
+        PROVIDE(__lga_dev_ld_early_end = .);
 
         /* ---- */
 
         . = ALIGN(8);
 
-        PROVIDE(__lga_inputdev_start = .);
+        PROVIDE(__lga_dev_ld_aftertimer_start = .);
         
-        KEEP(*(.lga.inputdev));
+        KEEP(*(.lga.devdefs.ld_aftertimer));
 
-        PROVIDE(__lga_inputdev_end = .);
+        PROVIDE(__lga_dev_ld_aftertimer_end = .);
 
         /* ---- */
 
         . = ALIGN(8);
 
-        PROVIDE(__lga_pseudo_dev_start = .);
+        PROVIDE(__lga_dev_ld_post_start = .);
         
-        KEEP(*(.lga.pseudo_dev));
+        KEEP(*(.lga.devdefs.ld_post));
+
+        PROVIDE(__lga_dev_ld_post_end = .);
+
+        /* ---- */
+
+        . = ALIGN(8);
+
+        PROVIDE(__lga_fs_start = .);
+        
+        KEEP(*(.lga.fs));
+
+        PROVIDE(__lga_fs_end = .);
 
-        PROVIDE(__lga_pseudo_dev_end = .);
     }
 
     .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) {