From f044ca812256b421e793c4335ce1ffed74710a70 Mon Sep 17 00:00:00 2001 From: Minep Date: Mon, 28 Aug 2023 22:47:39 +0100 Subject: [PATCH] feat: device subsystem rework + dynamic device driver registration and discovery + centeralise the device managements refactor: syslog --- lunaix-os/arch/i386/exceptions/i386_isrm.c | 3 +- lunaix-os/hal/ahci/ahci.c | 26 +- lunaix-os/hal/ahci/io_event.c | 6 +- .../device/pseudo => hal/char}/devnull.c | 14 +- lunaix-os/hal/char/ps2kbd.c | 25 +- lunaix-os/hal/pci.c | 264 +++++++++--------- lunaix-os/hal/rng/rngx86.c | 14 +- lunaix-os/hal/rtc/hwrtc.c | 15 +- lunaix-os/hal/rtc/mc146818a.c | 17 +- lunaix-os/hal/timer/hwtimer.c | 3 + lunaix-os/includes/hal/pci.h | 38 +-- lunaix-os/includes/lunaix/device.h | 119 +++++++- lunaix-os/includes/lunaix/device_num.h | 79 ++++++ lunaix-os/includes/lunaix/ds/hashtable.h | 4 +- lunaix-os/includes/lunaix/ds/ldga.h | 30 +- lunaix-os/includes/lunaix/fs.h | 4 + lunaix-os/includes/lunaix/isrm.h | 2 +- lunaix-os/includes/lunaix/lxconsole.h | 3 - lunaix-os/includes/lunaix/syslog.h | 3 + lunaix-os/kernel/device/devdb.c | 175 ++++++++++++ lunaix-os/kernel/device/devfs.c | 1 + lunaix-os/kernel/device/device.c | 78 ++++-- lunaix-os/kernel/device/input.c | 9 +- lunaix-os/kernel/device/pseudo/devpseudo.c | 18 -- lunaix-os/kernel/fs/fs_setup.c | 18 -- lunaix-os/kernel/fs/fsm.c | 2 +- lunaix-os/kernel/fs/iso9660/mount.c | 3 +- lunaix-os/kernel/fs/ramfs/ramfs.c | 1 + lunaix-os/kernel/fs/twifs/twifs.c | 8 +- lunaix-os/kernel/kinit.c | 12 +- lunaix-os/kernel/kprintf.c | 94 ++++--- lunaix-os/kernel/proc0.c | 12 +- lunaix-os/kernel/process/taskfs.c | 3 +- lunaix-os/kernel/time/clock.c | 2 +- lunaix-os/kernel/tty/lxconsole.c | 38 ++- lunaix-os/link/linker.ld | 35 ++- 36 files changed, 816 insertions(+), 362 deletions(-) rename lunaix-os/{kernel/device/pseudo => hal/char}/devnull.c (73%) create mode 100644 lunaix-os/includes/lunaix/device_num.h create mode 100644 lunaix-os/kernel/device/devdb.c delete mode 100644 lunaix-os/kernel/device/pseudo/devpseudo.c delete mode 100644 lunaix-os/kernel/fs/fs_setup.c diff --git a/lunaix-os/arch/i386/exceptions/i386_isrm.c b/lunaix-os/arch/i386/exceptions/i386_isrm.c index 2aabc39..0628535 100644 --- a/lunaix-os/arch/i386/exceptions/i386_isrm.c +++ b/lunaix-os/arch/i386/exceptions/i386_isrm.c @@ -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]; diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 8059760..c20e21d 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -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 diff --git a/lunaix-os/hal/ahci/io_event.c b/lunaix-os/hal/ahci/io_event.c index bb3142b..2ce49ef 100644 --- a/lunaix-os/hal/ahci/io_event.c +++ b/lunaix-os/hal/ahci/io_event.c @@ -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; diff --git a/lunaix-os/kernel/device/pseudo/devnull.c b/lunaix-os/hal/char/devnull.c similarity index 73% rename from lunaix-os/kernel/device/pseudo/devnull.c rename to lunaix-os/hal/char/devnull.c index 3e82bba..12bd007 100644 --- a/lunaix-os/kernel/device/pseudo/devnull.c +++ b/lunaix-os/hal/char/devnull.c @@ -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); diff --git a/lunaix-os/hal/char/ps2kbd.c b/lunaix-os/hal/char/ps2kbd.c index 47c866d..f59dcf3 100644 --- a/lunaix-os/hal/char/ps2kbd.c +++ b/lunaix-os/hal/char/ps2kbd.c @@ -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); diff --git a/lunaix-os/hal/pci.c b/lunaix-os/hal/pci.c index 1457aa1..9ac45d5 100644 --- a/lunaix-os/hal/pci.c +++ b/lunaix-os/hal/pci.c @@ -20,11 +20,80 @@ 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); diff --git a/lunaix-os/hal/rng/rngx86.c b/lunaix-os/hal/rng/rngx86.c index aea9b69..bb069d7 100644 --- a/lunaix-os/hal/rng/rngx86.c +++ b/lunaix-os/hal/rng/rngx86.c @@ -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 diff --git a/lunaix-os/hal/rtc/hwrtc.c b/lunaix-os/hal/rtc/hwrtc.c index c3fc197..5a53664 100644 --- a/lunaix-os/hal/rtc/hwrtc.c +++ b/lunaix-os/hal/rtc/hwrtc.c @@ -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) diff --git a/lunaix-os/hal/rtc/mc146818a.c b/lunaix-os/hal/rtc/mc146818a.c index 1a50765..e918ffd 100644 --- a/lunaix-os/hal/rtc/mc146818a.c +++ b/lunaix-os/hal/rtc/mc146818a.c @@ -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 diff --git a/lunaix-os/hal/timer/hwtimer.c b/lunaix-os/hal/timer/hwtimer.c index 3a79ca1..1a994f7 100644 --- a/lunaix-os/hal/timer/hwtimer.c +++ b/lunaix-os/hal/timer/hwtimer.c @@ -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; diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h index 2cc45b2..186c677 100644 --- a/lunaix-os/includes/hal/pci.h +++ b/lunaix-os/includes/hal/pci.h @@ -1,6 +1,7 @@ #ifndef __LUNAIX_PCI_H #define __LUNAIX_PCI_H +#include #include #include #include @@ -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. diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index 2634d81..52df8f0 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -3,6 +3,8 @@ #define DEVICE_NAME_SIZE 32 +#include +#include #include #include #include @@ -10,11 +12,49 @@ #include /** - * @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 @@ -27,6 +67,14 @@ 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 index 0000000..58e9122 --- /dev/null +++ b/lunaix-os/includes/lunaix/device_num.h @@ -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 */ diff --git a/lunaix-os/includes/lunaix/ds/hashtable.h b/lunaix-os/includes/lunaix/ds/hashtable.h index c3aea3f..41ca36b 100644 --- a/lunaix-os/includes/lunaix/ds/hashtable.h +++ b/lunaix-os/includes/lunaix/ds/hashtable.h @@ -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); \ diff --git a/lunaix-os/includes/lunaix/ds/ldga.h b/lunaix-os/includes/lunaix/ds/ldga.h index c436798..8c00bbe 100644 --- a/lunaix-os/includes/lunaix/ds/ldga.h +++ b/lunaix-os/includes/lunaix/ds/ldga.h @@ -13,9 +13,20 @@ #include +#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; \ @@ -24,4 +35,19 @@ (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 */ diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 5fbcc90..d90a773 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -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) == '_' || \ diff --git a/lunaix-os/includes/lunaix/isrm.h b/lunaix-os/includes/lunaix/isrm.h index e9f80b0..160350a 100644 --- a/lunaix-os/includes/lunaix/isrm.h +++ b/lunaix-os/includes/lunaix/isrm.h @@ -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); diff --git a/lunaix-os/includes/lunaix/lxconsole.h b/lunaix-os/includes/lunaix/lxconsole.h index 197bc9e..fbf59a4 100644 --- a/lunaix-os/includes/lunaix/lxconsole.h +++ b/lunaix-os/includes/lunaix/lxconsole.h @@ -11,9 +11,6 @@ void lxconsole_init(); -void -lxconsole_spawn_ttydev(); - void console_write_str(char* str); diff --git a/lunaix-os/includes/lunaix/syslog.h b/lunaix-os/includes/lunaix/syslog.h index 464a133..eed1da2 100644 --- a/lunaix-os/includes/lunaix/syslog.h +++ b/lunaix-os/includes/lunaix/syslog.h @@ -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 index 0000000..cf58a9d --- /dev/null +++ b/lunaix-os/kernel/device/devdb.c @@ -0,0 +1,175 @@ +#include +#include +#include + +#include + +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 diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c index 2951456..fb55d24 100644 --- a/lunaix-os/kernel/device/devfs.c +++ b/lunaix-os/kernel/device/devfs.c @@ -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, diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index 979b461..b794334 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -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; diff --git a/lunaix-os/kernel/device/input.c b/lunaix-os/kernel/device/input.c index 0680fef..52c8820 100644 --- a/lunaix-os/kernel/device/input.c +++ b/lunaix-os/kernel/device/input.c @@ -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 index 45ee4a4..0000000 --- a/lunaix-os/kernel/device/pseudo/devpseudo.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - -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 index 0966222..0000000 --- a/lunaix-os/kernel/fs/fs_setup.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void -fsm_register_all() -{ - ramfs_init(); - twifs_init(); - devfs_init(); - taskfs_init(); - iso9660_init(); - - // ... more fs implementation -} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/fsm.c b/lunaix-os/kernel/fs/fsm.c index a6a2be6..ca1221c 100644 --- a/lunaix-os/kernel/fs/fsm.c +++ b/lunaix-os/kernel/fs/fsm.c @@ -23,7 +23,7 @@ fsm_init() { hashtable_init(fs_registry); - fsm_register_all(); + ldga_invoke_fn0(fs); } void diff --git a/lunaix-os/kernel/fs/iso9660/mount.c b/lunaix-os/kernel/fs/iso9660/mount.c index 1989560..3849add 100644 --- a/lunaix-os/kernel/fs/iso9660/mount.c +++ b/lunaix-os/kernel/fs/iso9660/mount.c @@ -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 diff --git a/lunaix-os/kernel/fs/ramfs/ramfs.c b/lunaix-os/kernel/fs/ramfs/ramfs.c index fece9b3..e2d1263 100644 --- a/lunaix-os/kernel/fs/ramfs/ramfs.c +++ b/lunaix-os/kernel/fs/ramfs/ramfs.c @@ -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) diff --git a/lunaix-os/kernel/fs/twifs/twifs.c b/lunaix-os/kernel/fs/twifs/twifs.c index 729b5f7..4d987ae 100644 --- a/lunaix-os/kernel/fs/twifs/twifs.c +++ b/lunaix-os/kernel/fs/twifs/twifs.c @@ -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 diff --git a/lunaix-os/kernel/kinit.c b/lunaix-os/kernel/kinit.c index 0460544..f5944b5 100644 --- a/lunaix-os/kernel/kinit.c +++ b/lunaix-os/kernel/kinit.c @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -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 */ diff --git a/lunaix-os/kernel/kprintf.c b/lunaix-os/kernel/kprintf.c index 91646e9..15c8c14 100644 --- a/lunaix-os/kernel/kprintf.c +++ b/lunaix-os/kernel/kprintf.c @@ -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 diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index c7501af..4b430b5 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -18,8 +18,6 @@ #include -#include - #include 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 diff --git a/lunaix-os/kernel/process/taskfs.c b/lunaix-os/kernel/process/taskfs.c index 6ecdc8f..2aa1ed9 100644 --- a/lunaix-os/kernel/process/taskfs.c +++ b/lunaix-os/kernel/process/taskfs.c @@ -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 diff --git a/lunaix-os/kernel/time/clock.c b/lunaix-os/kernel/time/clock.c index be6b21b..ef557c7 100644 --- a/lunaix-os/kernel/time/clock.c +++ b/lunaix-os/kernel/time/clock.c @@ -54,7 +54,7 @@ EXPORT_TWIFS_PLUGIN(sys_clock, clock_build_mapping); void clock_init() { - hwrtc_init(); + // hwrtc_init(); } time_t diff --git a/lunaix-os/kernel/tty/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c index 8d0747d..0bcb9b7 100644 --- a/lunaix-os/kernel/tty/lxconsole.c +++ b/lunaix-os/kernel/tty/lxconsole.c @@ -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 diff --git a/lunaix-os/link/linker.ld b/lunaix-os/link/linker.ld index 52ce3eb..1cc64bb 100644 --- a/lunaix-os/link/linker.ld +++ b/lunaix-os/link/linker.ld @@ -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 ) { -- 2.27.0