this allow greater flexibility and decouple the pci bus scanning and the driver init dependency.
refactor: move acpi as a loadable device
refactor: remove the nonsense "len" parameter from {read|write}_page file ops
refactor: decouple the ahci main driver from the pci interfacing
refacror: move the mounting of some kernel fs to user space.
refactor: rename the device loading stage to make more sense.
chores: some house-keeping stuff
goto done;
}
- kprintf(KERROR "INT %u: (%x) [%p: %p] Unknown",
+ ERROR("INT %u: (%x) [%p: %p] Unknown",
execp->vector,
execp->err_code,
execp->cs,
void
__print_panic_msg(const char* msg, const isr_param* param)
{
- kprintf(KERROR "panic: %s", msg);
+ ERROR("panic: %s", msg);
trace_printstack_isr(param);
}
#include <klibc/string.h>
+LOG_MODULE("pf")
+
static u32_t
get_ptattr(struct mm_region* vmr)
{
return ptattr & 0xfff;
}
-static void
-kprintf(const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- __kprintf("PFAULT", fmt, args);
- va_end(args);
-}
-
#define COW_MASK (REGION_RSHARED | REGION_READ | REGION_WRITE)
extern void
if (PG_IS_PRESENT(*pte)) {
if (((errcode ^ mapping.flags) & PG_ALLOW_USER)) {
// invalid access
- kprintf(KDEBUG "invalid user access. (%p->%p, attr:0x%x)",
- mapping.va,
- mapping.pa,
- mapping.flags);
+ DEBUG("invalid user access. (%p->%p, attr:0x%x)",
+ mapping.va,
+ mapping.pa,
+ mapping.flags);
goto segv_term;
}
if ((hit_region->attr & COW_MASK) == COW_MASK) {
int errno = 0;
if (mseg_off < hit_region->flen) {
- errno =
- file->ops->read_page(file->inode, (void*)ptr, PG_SIZE, mfile_off);
+ errno = file->ops->read_page(file->inode, (void*)ptr, mfile_off);
}
if (errno < 0) {
- kprintf(KERROR "fail to populate page (%d)", errno);
+ ERROR("fail to populate page (%d)", errno);
goto segv_term;
}
;
oom:
- kprintf(KERROR "out of memory");
+ ERROR("out of memory");
segv_term:
- kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p,e=0x%x)",
- __current->pid,
- ptr,
- param->execp->cs,
- param->execp->eip,
- param->execp->err_code);
+ ERROR("(pid: %d) Segmentation fault on %p (%p:%p,e=0x%x)",
+ __current->pid,
+ ptr,
+ param->execp->cs,
+ param->execp->eip,
+ param->execp->err_code);
sigset_add(__current->sigctx.sig_pending, _SIGSEGV);
#include <hal/acpi/acpi.h>
+#include <lunaix/device.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
int
acpi_rsdp_validate(acpi_rsdp_t* rsdp);
-acpi_rsdp_t*
-acpi_locate_rsdp();
-
-int
-acpi_init()
-{
- acpi_rsdp_t* rsdp = acpi_locate_rsdp();
-
- assert_msg(rsdp, "Fail to locate ACPI_RSDP");
- assert_msg(acpi_rsdp_validate(rsdp), "Invalid ACPI_RSDP (checksum failed)");
-
- acpi_rsdt_t* rsdt = rsdp->rsdt;
-
- ctx = vzalloc(sizeof(acpi_context));
- assert_msg(ctx, "Fail to create ACPI context");
-
- strncpy(ctx->oem_id, rsdt->header.oem_id, 6);
- ctx->oem_id[6] = '\0';
-
- size_t entry_n = (rsdt->header.length - sizeof(acpi_sdthdr_t)) >> 2;
- for (size_t i = 0; i < entry_n; i++) {
- acpi_sdthdr_t* sdthdr =
- (acpi_sdthdr_t*)((acpi_apic_t**)&(rsdt->entry))[i];
- switch (sdthdr->signature) {
- case ACPI_MADT_SIG:
- madt_parse((acpi_madt_t*)sdthdr, ctx);
- break;
- case ACPI_FADT_SIG:
- // FADT just a plain structure, no need to parse.
- ctx->fadt = *(acpi_fadt_t*)sdthdr;
- break;
- case ACPI_MCFG_SIG:
- mcfg_parse(sdthdr, ctx);
- break;
- default:
- break;
- }
- }
-
- return 0;
-}
-
acpi_context*
acpi_get_context()
{
}
return rsdp;
-}
\ No newline at end of file
+}
+
+static int
+acpi_init(struct device_def* devdef)
+{
+ acpi_rsdp_t* rsdp = acpi_locate_rsdp();
+
+ assert_msg(rsdp, "Fail to locate ACPI_RSDP");
+ assert_msg(acpi_rsdp_validate(rsdp), "Invalid ACPI_RSDP (checksum failed)");
+
+ acpi_rsdt_t* rsdt = rsdp->rsdt;
+
+ ctx = vzalloc(sizeof(acpi_context));
+ assert_msg(ctx, "Fail to create ACPI context");
+
+ strncpy(ctx->oem_id, rsdt->header.oem_id, 6);
+ ctx->oem_id[6] = '\0';
+
+ size_t entry_n = (rsdt->header.length - sizeof(acpi_sdthdr_t)) >> 2;
+ for (size_t i = 0; i < entry_n; i++) {
+ acpi_sdthdr_t* sdthdr =
+ (acpi_sdthdr_t*)((acpi_apic_t**)&(rsdt->entry))[i];
+ switch (sdthdr->signature) {
+ case ACPI_MADT_SIG:
+ madt_parse((acpi_madt_t*)sdthdr, ctx);
+ break;
+ case ACPI_FADT_SIG:
+ // FADT just a plain structure, no need to parse.
+ ctx->fadt = *(acpi_fadt_t*)sdthdr;
+ break;
+ case ACPI_MCFG_SIG:
+ mcfg_parse(sdthdr, ctx);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+struct device_def acpi_sysdev = { .name = "ACPI Proxy",
+ .class =
+ DEVCLASS(DEVIF_FMW, DEVFN_CFG, DEV_ACPI),
+ .init = acpi_init };
+EXPORT_DEVICE(acpi, &acpi_sysdev, load_sysconf);
\ No newline at end of file
extern void
ahci_fsexport(struct block_dev* bdev, void* fs_node);
-extern void
-__ahci_hba_isr(const isr_param* param);
-
extern void
__ahci_blkio_handler(struct blkio_req* req);
port_reg[HBA_RPxSCTL] &= ~0xf;
}
-int
-ahci_driver_init(struct device_def* def, struct device* dev)
+struct ahci_driver*
+ahci_driver_init(struct ahci_driver_param* param)
{
- 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.");
-
- pci_reg_t cmd = pci_read_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD);
-
- // 禁用传统中断(因为我们使用MSI),启用MMIO访问,允许PCI设备间访问
- cmd |= (PCI_RCMD_MM_ACCESS | PCI_RCMD_DISABLE_INTR | PCI_RCMD_BUS_MASTER);
-
- pci_write_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD, cmd);
-
- 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;
- ahci_drv->id = iv;
+ ahci_drv->id = param->ahci_iv;
+
+ isrm_set_payload(param->ahci_iv, (ptr_t)&ahcis);
llist_append(&ahcis, &ahci_drv->ahci_drvs);
- hba->base = (hba_reg_t*)ioremap(bar6->start, bar6->size);
+ hba->base = (hba_reg_t*)ioremap(param->mmio_base, param->mmio_size);
#ifdef DO_HBA_FULL_RESET
// 重置HBA
port_regs[HBA_RPxCMD] |= HBA_PxCMD_ST;
if (!ahci_init_device(port)) {
- kprintf(KERROR "init fail: 0x%x@p%d", port->regs[HBA_RPxSIG], i);
+ ERROR("init fail: 0x%x@p%d", port->regs[HBA_RPxSIG], i);
continue;
}
ahci_register_device(hbadev);
}
- pci_bind_instance(ahci_dev, ahci_drv);
- return 0;
+ return ahci_drv;
}
void
port->device->ops.submit = scsi_submit;
}
}
-
-static struct pci_device_def ahcidef = {
- .dev_class = AHCI_HBA_CLASS,
- .ident_mask = PCI_MATCH_ANY,
- .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA),
- .name = "Serial ATA Controller",
- .bind = ahci_driver_init }
-};
-EXPORT_PCI_DEVICE(ahci, &ahcidef);
\ No newline at end of file
--- /dev/null
+#include <lunaix/spike.h>
+
+#include <hal/ahci/ahci.h>
+#include <hal/pci.h>
+#include <sys/pci_hba.h>
+
+static int
+ahci_pci_bind(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.");
+
+ pci_reg_t cmd = pci_read_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD);
+
+ // 禁用传统中断(因为我们使用MSI),启用MMIO访问,允许PCI设备间访问
+ cmd |= (PCI_RCMD_MM_ACCESS | PCI_RCMD_DISABLE_INTR | PCI_RCMD_BUS_MASTER);
+
+ pci_write_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD, cmd);
+
+ int iv = isrm_ivexalloc(ahci_hba_isr);
+ pci_setup_msi(ahci_dev, iv);
+
+ struct ahci_driver_param param = {
+ .mmio_base = bar6->start,
+ .mmio_size = bar6->size,
+ .ahci_iv = iv,
+ };
+
+ struct ahci_driver* ahci_drv = ahci_driver_init(¶m);
+ pci_bind_instance(ahci_dev, ahci_drv);
+
+ return 0;
+}
+
+static int
+ahci_pci_init(struct device_def* def)
+{
+ return pci_bind_definition_all(pcidev_def(def));
+}
+
+static struct pci_device_def ahcidef = {
+ .dev_class = AHCI_HBA_CLASS,
+ .ident_mask = PCI_MATCH_ANY,
+ .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA),
+ .name = "Generic SATA",
+ .init = ahci_pci_init,
+ .bind = ahci_pci_bind }
+};
+EXPORT_PCI_DEVICE(ahci, &ahcidef, load_postboot);
\ No newline at end of file
LOG_MODULE("io_evt")
void
-__ahci_hba_isr(const isr_param* param)
+ahci_hba_isr(const isr_param* param)
{
struct ahci_hba* hba;
struct ahci_driver *pos, *n;
.class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_NULL, DEV_BUILTIN_NULL),
.init = pdev_nulldev_init
};
-EXPORT_DEVICE(nulldev, &devnull_def, load_earlystage);
+EXPORT_DEVICE(nulldev, &devnull_def, load_onboot);
.class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_ZERO, DEV_BUILTIN_ZERO),
.init = pdev_zerodev_init
};
-EXPORT_DEVICE(zerodev, &devzero_def, load_earlystage);
+EXPORT_DEVICE(zerodev, &devzero_def, load_onboot);
// https://bochs.sourceforge.io/cgi-bin/lxr/source/bios/rombios32.c#L1314
// */
// if (!(acpi_ctx->fadt.boot_arch & IAPC_ARCH_8042)) {
- // kprintf(KERROR "not found\n");
+ // ERROR("not found\n");
// // FUTURE: Some alternative fallback on this? Check PCI bus for
// USB
// // controller instead?
// return;
// }
// } else {
- // kprintf(KWARN "outdated FADT used, assuming exists.\n");
+ // WARN("outdated FADT used, assuming exists.\n");
// }
char result;
// 4、控制器自检
result = ps2_issue_cmd_wretry(PS2_CMD_SELFTEST, PS2_NO_ARG);
if (result != PS2_RESULT_TEST_OK) {
- kprintf(KWARN "controller self-test failed. (%x)", result);
+ WARN("controller self-test failed. (%x)", result);
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)", result);
+ ERROR("interface test on port 1 failed. (%x)", result);
goto done;
}
#endif
#ifdef KBD_DBGLOG
- kprintf(KDEBUG "%x\n", scancode & 0xff);
+ DEBUG("%x\n", scancode & 0xff);
#endif
switch (kbd_state.state) {
c++;
}
if (c >= 5) {
- kprintf(KWARN "max attempt reached.");
+ WARN("max attempt reached.");
}
return r;
}
.class = DEVCLASS(DEVIF_SOC, DEVFN_INPUT, DEV_KBD),
.init = ps2_kbd_init
};
-EXPORT_DEVICE(i8042_kbd, &devrtc_i8042kbd, load_earlystage);
+EXPORT_DEVICE(i8042_kbd, &devrtc_i8042kbd, load_onboot);
.name = "16550 Generic UART (I/O)",
.init = upiom_init
};
-EXPORT_DEVICE(uart16550_pmio, &uart_pmio_def, load_earlystage);
\ No newline at end of file
+EXPORT_DEVICE(uart16550_pmio, &uart_pmio_def, load_onboot);
\ No newline at end of file
#define VGA_REG_OFF 0x0400
static int
-vga_pci_init(struct device_def* devdef, struct device* pcidev_base)
+vga_pci_bind(struct device_def* devdef, struct device* pcidev_base)
{
struct pci_device* pcidev = PCI_DEVICE(pcidev_base);
return 0;
}
+static int
+vga_pci_init(struct device_def* def)
+{
+ return pci_bind_definition_all(pcidev_def(def));
+}
+
#define VGA_PCI_CLASS 0x30000
static struct pci_device_def vga_pci_devdef = {
.ident_mask = PCI_MATCH_EXACT,
.devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_DISP, DEV_VGA),
.name = "Generic VGA",
- .bind = vga_pci_init }
+ .init = vga_pci_init,
+ .bind = vga_pci_bind }
};
-EXPORT_PCI_DEVICE(vga_pci, &vga_pci_devdef);
\ No newline at end of file
+EXPORT_PCI_DEVICE(vga_pci, &vga_pci_devdef, load_onboot);
\ No newline at end of file
pciaddr_t loc = pcidev->loc;
struct device_def* binddef = pcidev->binding.def;
- if (!binddef) {
- kprintf("pci.%d:%d:%d, no binding",
- PCILOC_BUS(loc),
- PCILOC_DEV(loc),
- PCILOC_FN(loc));
- return;
- }
-
- kprintf("pci.%d:%d:%d, dev.%xh:%xh.%d, %s",
+ kprintf("pci.%03d:%02d:%02d, class=%p, vendor:dev=%04x:%04x",
PCILOC_BUS(loc),
PCILOC_DEV(loc),
PCILOC_FN(loc),
- binddef->class.fn_grp,
- binddef->class.device,
- binddef->class.variant,
- binddef->name);
+ pcidev->class_info,
+ PCI_DEV_VENDOR(pcidev->device_info),
+ PCI_DEV_DEVID(pcidev->device_info));
}
static struct pci_device*
pci_create_device(pciaddr_t loc, 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);
device_register(&device->dev, &pci_def.class, "%x", loc);
pci_def.class.variant++;
- // find a suitable binding
+ return device;
+}
+
+int
+pci_bind_definition(struct pci_device_def* pcidev_def, int* more)
+{
+ u32_t class = pcidev_def->dev_class;
+ u32_t devid_mask = pcidev_def->ident_mask;
+ u32_t devid = pcidev_def->dev_ident & devid_mask;
+
+ if (!pcidev_def->devdef.bind) {
+ ERROR("pcidev %xh:%xh.%d is unbindable",
+ pcidev_def->devdef.class.fn_grp,
+ pcidev_def->devdef.class.device,
+ pcidev_def->devdef.class.variant);
+ return EINVAL;
+ }
- struct pci_device_def *pos, *n;
- hashtable_bucket_foreach(bucket, pos, n, devdef.hlist_if)
+ *more = 0;
+
+ int bind_attempted = 0;
+ int errno = 0;
+
+ struct device_def* devdef;
+ struct pci_device *pos, *n;
+ llist_for_each(pos, n, &pci_devices, dev_chain)
{
- if (pos->dev_class != PCI_DEV_CLASS(class)) {
+ if (binded_pcidev(pos)) {
+ continue;
+ }
+
+ if (class != PCI_DEV_CLASS(pos->class_info)) {
continue;
}
- u32_t idm = pos->ident_mask;
- int result = (pos->dev_ident & idm) == (devinfo & idm);
+ int matched = (pos->device_info & devid_mask) == devid;
- if (result) {
- goto found;
+ if (!matched) {
+ continue;
}
- }
- goto done;
+ if (bind_attempted) {
+ *more = 1;
+ break;
+ }
-found:
- if (!pos->devdef.bind) {
- kprintf(KERROR "pci_loc:%x, (%xh:%xh.%d) unbindable",
- loc,
- pos->devdef.class.fn_grp,
- pos->devdef.class.device,
- pos->devdef.class.variant);
- goto done;
- }
+ bind_attempted = 1;
+ devdef = &pcidev_def->devdef;
+ errno = devdef->bind(devdef, &pos->dev);
+
+ if (errno) {
+ ERROR("pci_loc:%x, bind (%xh:%xh.%d) failed, e=%d",
+ pos->loc,
+ devdef->class.fn_grp,
+ devdef->class.device,
+ devdef->class.variant,
+ errno);
+ continue;
+ }
- int errno = pos->devdef.bind(&pos->devdef, &device->dev);
- if (errno) {
- kprintf(KERROR "pci_loc:%x, (%xh:%xh.%d) failed, e=%d",
- loc,
- pos->devdef.class.fn_grp,
- pos->devdef.class.device,
- pos->devdef.class.variant,
- errno);
- goto done;
+ pos->binding.def = &pcidev_def->devdef;
}
- device->binding.def = &pos->devdef;
+ return errno;
+}
-done:
- return device;
+int
+pci_bind_definition_all(struct pci_device_def* pcidef)
+{
+ int more = 0, e = 0;
+ do {
+ if (!(e = pci_bind_definition(pcidef, &more))) {
+ break;
+ }
+ } while (more);
+
+ return e;
}
void
}
static struct device_def pci_def = {
- .name = "pci3.0-hba",
+ .name = "Generic PCI",
.class = DEVCLASS(DEVIF_SOC, DEVFN_BUSIF, DEV_PCI),
.init = pci_load_devices
};
-EXPORT_DEVICE(pci3hba, &pci_def, load_poststage);
+EXPORT_DEVICE(pci3hba, &pci_def, load_sysconf);
.class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_RNG),
.init = pdev_randdev_init
};
-EXPORT_DEVICE(randdev, &devrandx86_def, load_earlystage);
\ No newline at end of file
+EXPORT_DEVICE(randdev, &devrandx86_def, load_onboot);
\ No newline at end of file
// Make sure the rtc timer is disabled by default
rtc_disable_timer();
- struct hwrtc* rtc = hwrtc_alloc_new(devdef, "mc146818");
+ struct hwrtc* rtc = hwrtc_alloc_new("mc146818");
struct mc146818* state = valloc(sizeof(struct mc146818));
state->rtc_context = rtc;
rtc->get_counts = rtc_getcnt;
rtc->chfreq = rtc_chfreq;
+ hwrtc_register(&devdef->class, rtc);
+
return 0;
}
.class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC),
.init = rtc_init
};
-EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_earlystage);
\ No newline at end of file
+EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_timedev);
\ No newline at end of file
-#include <hal/hwrtc.h>
-
#include <lunaix/fs/twifs.h>
#include <lunaix/fs/twimap.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/status.h>
-#include <usr/lunaix/ioctl_defs.h>
+#include <hal/hwrtc.h>
-const struct hwrtc* primary_rtc;
+const struct hwrtc* sysrtc;
static int rtc_count = 0;
DEFINE_LLIST(rtcs);
-// void
-// hwrtc_init()
-// {
-// ldga_invoke_fn0(rtcdev);
-// }
-
void
hwrtc_walltime(datetime_t* dt)
{
- primary_rtc->get_walltime(primary_rtc, dt);
+ sysrtc->get_walltime(sysrtc, dt);
}
static int
}
struct hwrtc*
-hwrtc_alloc_new(struct device_def* def, char* name)
+hwrtc_alloc_new(char* name)
{
struct hwrtc* rtc_instance = valloc(sizeof(struct hwrtc));
llist_append(&rtcs, &rtc_instance->rtc_list);
- if (!primary_rtc) {
- primary_rtc = rtc_instance;
- }
-
+ rtc_instance->id = rtc_count++;
rtc_instance->name = name;
struct device* rtcdev = device_allocsys(NULL, rtc_instance);
rtc_instance->rtc_dev = rtcdev;
- device_register(rtcdev, &def->class, "rtc%d", def->class.variant);
+ return rtc_instance;
+}
- def->class.variant++;
+void
+hwrtc_register(struct devclass* class, struct hwrtc* rtc)
+{
+ if (unlikely(!sysrtc)) {
+ sysrtc = rtc;
+ }
- return rtc_instance;
+ class->variant = rtc->id;
+ device_register(rtc->rtc_dev, class, "rtc%d", rtc->id);
}
static void
__hwrtc_readinfo(struct twimap* mapping)
{
struct hwrtc* rtc = twimap_data(mapping, struct hwrtc*);
- twimap_printf(mapping, "device: %s\n", rtc->name);
+ twimap_printf(mapping, "name: %s\n", rtc->name);
twimap_printf(mapping, "frequency: %dHz\n", rtc->base_freq);
twimap_printf(mapping, "ticks count: %d\n", rtc->get_counts(rtc));
twimap_printf(
hwrtc_twifs_export(pos);
}
}
-EXPORT_TWIFS_PLUGIN(rtc_fsexport, hwrtc_twifs_export_all);
\ No newline at end of file
+EXPORT_TWIFS_PLUGIN(rtc_fsexport, hwrtc_twifs_export_all);
#include <hal/apic_timer.h>
-#include <hal/hwrtc.h>
#include <hal/hwtimer.h>
+#include <lunaix/clock.h>
#include <lunaix/compiler.h>
#include <lunaix/isrm.h>
#include <lunaix/spike.h>
#ifdef __LUNAIXOS_DEBUG__
if (frequency < 1000) {
- kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy.");
+ WARN("Frequency too low. Millisecond timer might be dodgy.");
}
#endif
apic_timer_done = 0;
- primary_rtc->cls_mask(primary_rtc);
+ sysrtc->cls_mask(sysrtc);
apic_write_reg(APIC_TIMER_ICR, APIC_BASETICKS); // start APIC timer
// enable interrupt, just for our RTC start ticking!
cpu_disable_interrupt();
- primary_rtc->set_mask(primary_rtc);
+ sysrtc->set_mask(sysrtc);
- base_freq = primary_rtc->get_counts(primary_rtc);
- base_freq = APIC_BASETICKS / base_freq * primary_rtc->base_freq;
+ base_freq = sysrtc->get_counts(sysrtc);
+ base_freq = APIC_BASETICKS / base_freq * sysrtc->base_freq;
assert_msg(base_freq, "Fail to initialize timer (NOFREQ)");
- kprintf(KINFO "hw: %u Hz; os: %u Hz", base_freq, frequency);
+ kprintf("hw: %u Hz; os: %u Hz", base_freq, frequency);
// cleanup
isrm_ivfree(iv_timer);
-#include <hal/hwtimer.h>
#include <lunaix/spike.h>
+#include <lunaix/time.h>
-#include <usr/lunaix/ioctl_defs.h>
+#include <hal/hwtimer.h>
-struct hwtimer* current_timer;
+const struct hwtimer* systimer;
ticks_t
hwtimer_base_frequency()
{
- assert(current_timer);
- return current_timer->base_freq;
+ assert(systimer);
+ return systimer->base_freq;
}
ticks_t
hwtimer_current_systicks()
{
- assert(current_timer);
- return current_timer->systicks();
+ assert(systimer);
+ return systimer->systicks();
}
ticks_t
hwtimer_to_ticks(u32_t value, int unit)
{
- assert(current_timer);
+ assert(systimer);
// in case system frequency is less than 1000Hz
if (unit != TIME_MS) {
- return current_timer->running_freq * unit * value;
+ return systimer->running_freq * unit * value;
}
- ticks_t freq_ms = current_timer->running_freq / 1000;
+ ticks_t freq_ms = systimer->running_freq / 1000;
return freq_ms * value;
}
hwt_ctx->init(hwt_ctx, hertz, tick_callback);
hwt_ctx->running_freq = hertz;
- current_timer = hwt_ctx;
+ systimer = hwt_ctx;
struct device* timerdev = device_allocsys(NULL, hwt_ctx);
struct acpi_mcfg_toc mcfg;
} acpi_context;
-int
-acpi_init();
-
acpi_context*
acpi_get_context();
#define __LUNAIX_AHCI_H
#include "hba.h"
+#include <lunaix/isrm.h>
/*
* Macro naming rule:
int id;
};
+struct ahci_driver_param
+{
+ ptr_t mmio_base;
+ size_t mmio_size;
+ int ahci_iv;
+};
+
void
ahci_parse_dev_info(struct hba_device* dev_info, u16_t* data);
void
ahci_post(struct hba_port* port, struct hba_cmd_state* state, int slot);
+struct ahci_driver*
+ahci_driver_init(struct ahci_driver_param* param);
+
+void
+ahci_hba_isr(const isr_param* param);
+
#endif /* __LUNAIX_AHCI_H */
struct llist_header rtc_list;
struct device* rtc_dev;
+ int id;
char* name;
void* data;
ticks_t base_freq;
int (*chfreq)(struct hwrtc*, int);
};
-extern const struct hwrtc* primary_rtc;
-
-void
-hwrtc_init();
-
struct hwrtc*
-hwrtc_alloc_new(struct device_def* def, char* name);
+hwrtc_alloc_new(char* name);
void
hwrtc_walltime(datetime_t* dt);
+void
+hwrtc_register(struct devclass* class, struct hwrtc* rtc);
+
#endif /* __LUNAIX_HWRTC_H */
ticks_t running_freq;
};
-extern struct hwtimer* current_timer;
-
void
hwtimer_init(u32_t hertz, void* tick_callback);
#include <lunaix/ds/llist.h>
#include <lunaix/types.h>
-#define EXPORT_PCI_DEVICE(id, pci_devdef) \
- EXPORT_DEVICE(id, &(pci_devdef)->devdef, load_pci_probe)
+#define EXPORT_PCI_DEVICE(id, pci_devdef, stage) \
+ EXPORT_DEVICE(id, &(pci_devdef)->devdef, stage)
#define PCI_MATCH_EXACT -1
#define PCI_MATCH_ANY 0
};
#define PCI_DEVICE(devbase) (container_of((devbase), struct pci_device, dev))
+struct pci_device_list
+{
+ struct llist_header peers;
+ struct pci_device* pcidev;
+};
+
typedef void* (*pci_drv_init)(struct pci_device*);
#define PCI_DEVIDENT(vendor, id) \
u32_t ident_mask;
struct device_def devdef;
};
+#define pcidev_def(dev_def_ptr) \
+ container_of((dev_def_ptr), struct pci_device_def, devdef)
+
+#define binded_pcidev(pcidev) ((pcidev)->binding.def)
/**
* @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备
void
pci_probe_msi_info(struct pci_device* device);
+int
+pci_bind_definition(struct pci_device_def* pcidev_def, int* more);
+
+int
+pci_bind_definition_all(struct pci_device_def* pcidef);
+
#endif /* __LUNAIX_PCI_H */
#define BLKIO_PENDING 0x8
#define BLKIO_WAIT 0x1
+#define BLKIO_NOASYNC 0x2
// Free on complete
#define BLKIO_FOC 0x10
#define __LUNAIX_CLOCK_H
#include <lunaix/time.h>
+
+#include <hal/hwrtc.h>
+#include <hal/hwtimer.h>
+
+extern const struct hwrtc* sysrtc;
+extern const struct hwtimer* systimer;
+
+void
+clock_init();
+
void
clock_walltime(datetime_t* datetime);
#define stringify(v) #v
#define stringify__(v) stringify(v)
+inline static void noret
+spin()
+{
+ volatile int __infloop = 1;
+ while (__infloop)
+ ;
+ __builtin_unreachable();
+}
+
#endif /* __LUNAIX_COMPILER_H */
#include <usr/lunaix/device.h>
/**
- * @brief Export a device definition
+ * @brief Export a device definition (i.e., device driver metadata)
*
*/
#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);
+/**
+ * @brief Mark the device definition can be loaded on demand, all other loading
+ * options are extended from this
+ */
#define load_on_demand ld_ondemand
-#define load_pci_probe 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
+ * @brief Mark the device definition to be loaded as system configuration
+ * device. These kind of devices are defined to be the devices that talk to the
+ * system firmware to do config, or collecting crucial information about the
+ * system. For instances, ACPI, SoC components, and other **interconnection**
+ * buese (not USB!). Such device driver must only rely on basic memory
+ * management service, and must not try accessing subsystems other than the mm
+ * unit, for example, timer, interrupt, file-system, must not assumed exist.
*
*/
-#define load_earlystage ld_early
+#define load_sysconf ld_sysconf
+
+/**
+ * @brief Mark the device definition should be loaded as time device, for
+ * example a real time clock device. Such device will be loaded and managed by
+ * clock subsystem
+ */
+#define load_timedev ld_timedev
/**
- * @brief Mark the device definition should be loaded automatically after timer
- * is ready. Load here if your driver require a basic timing service
+ * @brief Mark the device definition should be loaded automatically during the
+ * bootstrapping stage. Most of the driver do load there.
*
*/
-#define load_timerstage ld_aftertimer
+#define load_onboot ld_kboot
/**
* @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
+ * the post boostrapping stage (i.e., the start up of proc0), where most of
+ * kernel sub-system are became ready to use. Do your load there if your driver
+ * depends on such condition
*
*/
-#define load_poststage ld_post
+#define load_postboot ld_post
+
+#define __foreach_exported_device_of(stage, index, pos) \
+ ldga_foreach(dev_##stage, struct device_def*, index, pos)
+#define foreach_exported_device_of(stage, index, pos) \
+ __foreach_exported_device_of(stage, index, pos)
/**
* @brief Declare a device class
struct devclass class;
+ /**
+ * @brief Called when the driver is required to initialize itself.
+ *
+ */
int (*init)(struct device_def*);
+
+ /**
+ * @brief Called when the driver is required to bind with a device. This is
+ * the case for a real-hardware-oriented driver
+ *
+ */
int (*bind)(struct device_def*, struct device*);
+
+ /**
+ * @brief Called when a driver is requested to detach from the device and
+ * free up all it's resources
+ *
+ */
int (*free)(struct device_def*, void* instance);
};
/*------ Load hooks ------*/
void
-device_earlystage();
+device_onbooot_load();
void
-device_poststage();
+device_postboot_load();
void
-device_timerstage();
+device_sysconf_load();
static inline void
device_lock(struct device* dev)
I2C: device connected through the IIC protocol
+ FMW: device is a system board firmware
+
The function defines the functionality that the device is designated to
serve. Lunaix identify the following values:
TTY: a device which can be called as teletypewriter, system can use such
device for output into external environment
+
+ CFG: device that provide configuration service to the system or other
+ devices
+
+
*/
#define DEV_FNGRP(if_, function) \
#define DEVIF_USB 0x3
#define DEVIF_SPI 0x4
#define DEVIF_I2C 0x5
+#define DEVIF_FMW 0x6
#define DEVFN_PSEUDO 0x0
#define DEVFN_CHAR 0x1
#define DEVFN_BUSIF 0x7
#define DEVFN_TTY 0x8
#define DEVFN_DISP 0x9
+#define DEVFN_CFG 0xa
#define DEV_BUILTIN 0
#define DEV_BUILTIN_NULL 0
#define DEV_KBD 11
#define DEV_GFXA 12
#define DEV_VGA 13
+#define DEV_ACPI 14
struct devident
{
// These additional operations allow underlying fs to use more specialized
// and optimized code.
- int (*write_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
- int (*read_page)(struct v_inode* inode, void* pg, size_t len, size_t fpos);
+ int (*write_page)(struct v_inode* inode, void* pg, size_t fpos);
+ int (*read_page)(struct v_inode* inode, void* pg, size_t fpos);
int (*readdir)(struct v_file* file, struct dir_context* dctx);
int (*seek)(struct v_inode* inode, size_t offset); // optional
size_t len,
size_t fpos);
+int
+default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos);
+
+int
+default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos);
+
int
default_file_readdir(struct v_file* file, struct dir_context* dctx);
#define ISO_SIGNATURE_HI 0x31
// Volume Types
-#define ISO_VOLBOOT 0 // Boot Record
-#define ISO_VOLPRIM 1 // Primary
-#define ISO_VOLSUPP 2 // Supplementary
-#define ISO_VOLPART 3 // Partition
-#define ISO_VOLTERM 255 // Volume descriptor set terminator
+#define ISO_VOLBOOT 0 // Boot Record
+#define ISO_VOLPRIM 1 // Primary
+#define ISO_VOLSUPP 2 // Supplementary
+#define ISO_VOLPART 3 // Partition
+#define ISO_VOLTERM 255 // Volume descriptor set terminator
#define ISO_FHIDDEN 0x1 // a hidden file
#define ISO_FDIR 0x2 // a directory file
iso_bbo32_t data_size;
struct iso_datetime2 mktime; // Time the record is made, see 9.1.5
u8_t flags;
- u8_t fu_sz; // size of file unit (FU)
- u8_t gap_sz; // size of gap if FU is interleaved.
+ u8_t fu_sz; // size of file unit (FU)
+ u8_t gap_sz; // size of gap if FU is interleaved.
iso_bbo16_t vol_seq;
struct iso_var_mdu name;
} PACKED;
int
iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
+int
+iso9660_read_page(struct v_inode* inode, void* buffer, size_t fpos);
+
+int
+iso9660_write_page(struct v_inode* inode, void* buffer, size_t fpos);
+
int
iso9660_seek(struct v_inode* inode, size_t offset);
: 0) \
: (31 - __builtin_clz(x)))
-inline static void noret
-spin()
-{
- volatile int __infloop = 1;
- while (__infloop)
- ;
- __builtin_unreachable();
-}
-
#ifndef __LUNAIXOS_NASSERT__
#define assert(cond) \
if (!(cond)) { \
#define KLOG_ERROR 3
#define KLOG_FATAL 4
-#define _LEVEL_INFO "0"
-#define _LEVEL_WARN "1"
-#define _LEVEL_ERROR "2"
-#define _LEVEL_DEBUG "3"
-
#define KMSG_LVLSTART '\x1b'
#define KMSG_LOGLEVEL(c) ((c) - '0')
{ \
va_list args; \
va_start(args, fmt); \
- __kprintf(module, fmt, args); \
+ kprintf_m(module, fmt, args); \
va_end(args); \
}
+#define DEBUG(fmt, ...) kprintf(KDEBUG fmt, ##__VA_ARGS__)
+#define WARN(fmt, ...) kprintf(KWARN fmt, ##__VA_ARGS__)
+#define ERROR(fmt, ...) kprintf(KERROR fmt, ##__VA_ARGS__)
+#define FATAL(fmt, ...) \
+ ({ \
+ kprintf(KFATAL fmt, ##__VA_ARGS__); \
+ spin(); \
+ })
+
void
-__kprintf(const char* component, const char* fmt, va_list args);
+kprintf_m(const char* component, const char* fmt, va_list args);
+
+// TODO need more thought on it
+
+// struct klog_chunk
+// {
+// void* log_entry;
+// size_t max_len;
+// size_t len;
+// };
+
+// struct klog_chunk*
+// kprintf_lcstart_m(const char* component, size_t size);
+
+// void
+// kprintf_lcappend_m(struct klog_chunk*, const char* fmt, va_list args);
+
+// void
+// kprintf_lcdone_m(struct klog_chunk*);
#endif /* __LUNAIX_SYSLOG_H */
struct trace_record
{
ptr_t pc;
+ ptr_t sym_pc;
char* symbol;
};
u32_t crc = gpt_hdr->hdr_cksum;
gpt_hdr->hdr_cksum = 0;
if (crc32b((void*)gpt_hdr, sizeof(*gpt_hdr)) != crc) {
- kprintf(KWARN "checksum failed");
+ WARN("checksum failed");
// FUTURE check the backup header
return EINVAL;
}
blk_parent_dev = device_addcat(NULL, "block");
}
+static int
+__block_commit(struct blkio_context* blkio, struct blkio_req* req, int flags)
+{
+ int errno;
+ blkio_commit(blkio, req, flags);
+
+ if ((errno = req->errcode)) {
+ errno = -errno;
+ }
+
+ vbuf_free(req->vbuf);
+ blkio_free_req(req);
+ return errno;
+}
+
int
__block_read(struct device* dev, void* buf, size_t offset, size_t len)
{
}
req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
- blkio_commit(bdev->blkio, req, BLKIO_WAIT);
- if (!(errno = req->errcode)) {
+ if (!(errno = __block_commit(bdev->blkio, req, BLKIO_WAIT))) {
memcpy(buf, head_buf + r, rd_size);
errno = len;
- } else {
- errno = -errno;
}
if (head_buf) {
vfree(head_buf);
}
- blkio_free_req(req);
- vbuf_free(vbuf);
return errno;
}
}
req = blkio_vwr(vbuf, wr_block, NULL, NULL, 0);
- blkio_commit(bdev->blkio, req, BLKIO_WAIT);
- int errno = req->errcode;
- if (!errno) {
+ int errno;
+ if (!(errno = __block_commit(bdev->blkio, req, BLKIO_WAIT))) {
errno = len;
- } else {
- errno = -errno;
}
if (tmp_buf) {
vfree(tmp_buf);
}
- blkio_free_req(req);
- vbuf_free(vbuf);
return errno;
}
struct blkio_req* req = blkio_vrd(vbuf, lba, NULL, NULL, 0);
- blkio_commit(bdev->blkio, req, BLKIO_WAIT);
-
- int errno = req->errcode;
- if (!errno) {
+ int errno;
+ if (!(errno = __block_commit(bdev->blkio, req, BLKIO_WAIT))) {
errno = rd_lba * bdev->blk_size;
- } else {
- errno = -errno;
}
- blkio_free_req(req);
- vbuf_free(vbuf);
return errno;
}
struct block_dev* bdev = (struct block_dev*)dev->underlay;
u32_t lba = offset / bdev->blk_size + bdev->start_lba;
- u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
+ u32_t wr_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
- if (rd_lba <= lba) {
+ if (wr_lba <= lba) {
return 0;
}
- rd_lba -= lba;
+ wr_lba -= lba;
- vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
+ vbuf_alloc(&vbuf, buf, wr_lba * bdev->blk_size);
struct blkio_req* req = blkio_vwr(vbuf, lba, NULL, NULL, 0);
- blkio_commit(bdev->blkio, req, BLKIO_WAIT);
-
- int errno = req->errcode;
- if (!errno) {
- errno = rd_lba * bdev->blk_size;
- } else {
- errno = -errno;
+ int errno;
+ if (!(errno = __block_commit(bdev->blkio, req, BLKIO_WAIT))) {
+ errno = wr_lba * bdev->blk_size;
}
- blkio_free_req(req);
- vbuf_free(vbuf);
return errno;
}
vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
struct blkio_req* req = blkio_vrd(vbuf, start, NULL, NULL, 0);
- blkio_commit(bdev->blkio, req, BLKIO_WAIT);
- int errno = req->errcode;
- if (!errno) {
+ int errno;
+ if (!(errno = __block_commit(bdev->blkio, req, BLKIO_WAIT))) {
errno = count;
- } else {
- errno = -errno;
}
- blkio_free_req(req);
- vbuf_free(vbuf);
-
return errno;
}
vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
struct blkio_req* req = blkio_vwr(vbuf, start, NULL, NULL, 0);
- blkio_commit(bdev->blkio, req, BLKIO_WAIT);
- int errno = req->errcode;
- if (!errno) {
+ int errno;
+ if (!(errno = __block_commit(bdev->blkio, req, BLKIO_WAIT))) {
errno = count;
- } else {
- errno = -errno;
}
- blkio_free_req(req);
- vbuf_free(vbuf);
-
return errno;
}
errno = blkpart_probegpt(bdev->dev);
if (errno < 0) {
- kprintf(KERROR "Fail to parse partition table (%d)", errno);
+ ERROR("Fail to parse partition table (%d)", errno);
} else if (!errno) {
// TODO try other PT parser...
}
return errno;
error:
- kprintf(KERROR "Fail to mount block device: %s (%x)", bdev->name, -errno);
+ ERROR("Fail to mount block device: %s (%x)", bdev->name, -errno);
return errno;
}
sdbg_imm(const isr_param* param)
{
struct exec_param* execp = param->execp;
- kprintf(KDEBUG "Quick debug mode\n");
- kprintf(KDEBUG "cs=%p eip=%p eax=%p ebx=%p\n",
+ DEBUG("Quick debug mode\n");
+ DEBUG("cs=%p eip=%p eax=%p ebx=%p\n",
execp->cs,
execp->eip,
param->registers.eax,
param->registers.ebx);
- kprintf(KDEBUG "ecx=%p edx=%p edi=%p esi=%p\n",
+ DEBUG("ecx=%p edx=%p edi=%p esi=%p\n",
param->registers.ecx,
param->registers.edx,
param->registers.edi,
param->registers.esi);
- kprintf(KDEBUG "u.esp=%p k.esp=%p ebp=%p ps=%p\n",
+ DEBUG("u.esp=%p k.esp=%p ebp=%p ps=%p\n",
param->esp,
execp->esp,
param->registers.ebp,
execp->eflags);
- kprintf(KDEBUG "ss=%p ds=%p es=%p fs=%p gs=%p\n",
+ DEBUG("ss=%p ds=%p es=%p fs=%p gs=%p\n",
execp->ss,
param->registers.ds,
param->registers.es,
struct serial_dev* sdev = serial_get_avilable();
if (!sdev) {
- kprintf(KERROR "no serial port available\n");
+ ERROR("no serial port available\n");
return;
}
ptr_t pc = *(frame + 1);
current = trace_sym_lookup(pc);
- tb_buffer[i] = (struct trace_record){ .pc = current ? current->pc : pc,
- .symbol = ksym_getstr(current) };
+ tb_buffer[i] =
+ (struct trace_record){ .pc = pc,
+ .sym_pc = current ? current->pc : 0,
+ .symbol = ksym_getstr(current) };
frame = (ptr_t*)*frame;
i++;
return i;
}
+static inline void
+trace_print_code_entry(ptr_t sym_pc, ptr_t inst_pc, char* sym)
+{
+ DEBUG("%p+%p: %s", sym_pc, inst_pc - sym_pc, sym);
+}
+
void
trace_printstack_of(ptr_t fp)
{
struct trace_record tbs[NB_TRACEBACK];
+ // Let's get our Stackwalker does his job ;)
int n = trace_walkback(tbs, fp, NB_TRACEBACK, &fp);
if (fp) {
- kprintf(KDEBUG "...<truncated>");
+ DEBUG("...<truncated>");
}
for (int i = 0; i < n; i++) {
- kprintf(KDEBUG "%p: %s", tbs[i].pc, tbs[i].symbol);
+ struct trace_record* tb = &tbs[i];
+ trace_print_code_entry(tb->sym_pc, tb->pc, tb->symbol);
}
}
struct ksym_entry* sym = trace_sym_lookup(p->execp->eip);
- kprintf(KDEBUG ">> (sw:%s) iv:%d, errno:%p <<",
- direction,
- p->execp->vector,
- p->execp->err_code);
- kprintf(KDEBUG "%p:%s", p->execp->eip, ksym_getstr(sym));
+ DEBUG(">> (sw:%s) iv:%d, errno:%p <<",
+ direction,
+ p->execp->vector,
+ p->execp->err_code);
+
+ trace_print_code_entry(sym->pc, p->execp->eip, ksym_getstr(sym));
}
void
ptr_t fp = cpu_get_fp();
int prev_fromusr = 0;
- kprintf(KDEBUG "stack trace (pid=%d)\n", __current->pid);
+ DEBUG("stack trace (pid=%d)\n", __current->pid);
trace_printstack_of(fp);
return &dev_byif[__hashkey(dev_byif, if_type)];
}
-#define device_load_on_stage(stage) \
+#define __device_load_on_stage(stage) \
({ \
int idx = 0; \
struct device_def* devdef; \
- ldga_foreach(dev_ld_##stage, struct device_def*, idx, devdef) \
+ ldga_foreach(dev_##stage, struct device_def*, idx, devdef) \
{ \
devdef->init(devdef); \
} \
})
+#define device_load_on_stage(stage) __device_load_on_stage(stage)
void
-device_earlystage()
+device_onbooot_load()
{
- device_load_on_stage(early);
+ device_load_on_stage(load_onboot);
}
void
-device_timerstage()
+device_postboot_load()
{
- device_load_on_stage(aftertimer);
+ device_load_on_stage(load_postboot);
}
void
-device_poststage()
+device_sysconf_load()
{
- device_load_on_stage(post);
+ device_load_on_stage(load_sysconf);
}
static int
}
int
-devfs_read_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+devfs_read_page(struct v_inode* inode, void* buffer, size_t fpos)
{
assert(inode->data);
}
int
-devfs_write_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+devfs_write_page(struct v_inode* inode, void* buffer, size_t fpos)
{
assert(inode->data);
return ENOTSUP;
}
+int
+default_file_read_page(struct v_inode* inode, void* buffer, size_t fpos)
+{
+ return ENOTSUP;
+}
+
+int
+default_file_write_page(struct v_inode* inode, void* buffer, size_t fpos)
+{
+ return ENOTSUP;
+}
+
int
default_file_readdir(struct v_file* file, struct dir_context* dctx)
{
#include <lunaix/spike.h>
#include <klibc/string.h>
+#include <sys/mm/mempart.h>
int
iso9660_open(struct v_inode* this, struct v_file* file)
return errno;
}
+int
+iso9660_read_page(struct v_inode* inode, void* buffer, size_t fpos)
+{
+ return iso9660_read(inode, buffer, MEM_PAGE, fpos);
+}
+
int
iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
{
return ENOTSUP;
}
+int
+iso9660_write_page(struct v_inode* inode, void* buffer, size_t fpos)
+{
+ // TODO
+ return ENOTSUP;
+}
+
int
iso9660_seek(struct v_inode* inode, size_t offset)
{
static struct v_file_ops iso_file_ops = { .close = iso9660_close,
.read = iso9660_read,
- .read_page = iso9660_read,
+ .read_page = iso9660_read_page,
.write = iso9660_write,
- .write_page = iso9660_write,
+ .write_page = iso9660_write_page,
.seek = iso9660_seek,
.readdir = iso9660_readdir };
return errno;
cleanup:
- kprintf(KERROR "mount: dev=%s, fs=%s, mode=%d, err=%d",
- dev_name,
- fs_name,
- options,
- errno);
+ ERROR("mount: dev=%s, fs=%s, mode=%d, err=%d",
+ dev_name,
+ fs_name,
+ options,
+ errno);
mnt_point->super_block = old_sb;
vfs_sb_free(sb);
return errno;
int,
options)
{
- struct v_dnode *dev, *mnt;
+ struct v_dnode *dev = NULL, *mnt = NULL;
int errno = 0;
- if ((errno = vfs_walk(__current->cwd, source, &dev, NULL, 0))) {
- goto done;
- }
+ // It is fine if source is not exist, as some mounting don't require it
+ vfs_walk(__current->cwd, source, &dev, NULL, 0);
if ((errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
goto done;
// By our convention.
// XXX could we do better?
- struct device* device = (struct device*)dev->inode->data;
+ struct device* device = NULL;
- if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) {
- errno = ENOTDEV;
- goto done;
+ if (dev) {
+ if (!(dev->inode->itype & VFS_IFVOLDEV)) {
+ errno = ENOTDEV;
+ goto done;
+ }
+ device = (struct device*)dev->inode->data;
}
errno = vfs_mount_at(fstype, device, mnt, options);
struct hstr* component,
int options)
{
+ if (!path) {
+ *dentry = NULL;
+ return 0;
+ }
+
// allocate a file name stack for path walking and recursion to resolve
// symlink
char* name_buffer = valloc(2048);
if (new_page) {
// Filling up the page
- errno =
- inode->default_fops->read_page(inode, pg->pg, PG_SIZE, pg->fpos);
+ errno = inode->default_fops->read_page(inode, pg->pg, pg->fpos);
if (errno < 0) {
break;
int new_page = pcache_get_page(pcache, fpos, &pg_off, &pg);
if (new_page) {
// Filling up the page
- errno =
- inode->default_fops->read_page(inode, pg->pg, PG_SIZE, pg->fpos);
+ errno = inode->default_fops->read_page(inode, pg->pg, pg->fpos);
if (errno < 0) {
break;
pg->len = errno;
} else if (!pg) {
- errno = inode->default_fops->read_page(
+ errno = inode->default_fops->read(
inode, (data + buf_off), len - buf_off, pg->fpos);
buf_off = len;
break;
return 0;
}
- int errno =
- inode->default_fops->write_page(inode, page->pg, PG_SIZE, page->fpos);
+ int errno = inode->default_fops->write_page(inode, page->pg, page->fpos);
if (!errno) {
page->flags &= ~PCACHE_DIRTY;
const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
.close = default_file_close,
.read = default_file_read,
- .read_page = default_file_read,
+ .read_page = default_file_read_page,
.write = default_file_write,
- .write_page = default_file_write,
+ .write_page =
+ default_file_write_page,
.seek = default_file_seek };
\ No newline at end of file
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
+#include <sys/mm/mempart.h>
+
static struct twifs_node* fs_root;
static struct cake_pile* twi_pile;
return twi_node->ops.write(inode, buffer, len, fpos);
}
+int
+__twifs_fwrite_pg(struct v_inode* inode, void* buffer, size_t fpos)
+{
+ return __twifs_fwrite(inode, buffer, MEM_PAGE, fpos);
+}
+
int
__twifs_fread(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
{
return twi_node->ops.read(inode, buffer, len, fpos);
}
+int
+__twifs_fread_pg(struct v_inode* inode, void* buffer, size_t fpos)
+{
+ return __twifs_fread(inode, buffer, MEM_PAGE, fpos);
+}
+
struct twifs_node*
__twifs_get_node(struct twifs_node* parent, struct hstr* name)
{
const struct v_file_ops twifs_file_ops = { .close = default_file_close,
.read = __twifs_fread,
- .read_page = __twifs_fread,
+ .read_page = __twifs_fread_pg,
.write = __twifs_fwrite,
- .write_page = __twifs_fwrite,
+ .write_page = __twifs_fwrite_pg,
.readdir = __twifs_iterate_dir };
const struct v_inode_ops twifs_inode_ops = { .dir_lookup = __twifs_dirlookup,
#include <klibc/strfmt.h>
#include <klibc/string.h>
-#define TWIMAP_BUFFER_SIZE 4096
+#include <sys/mm/mempart.h>
+
+#define TWIMAP_BUFFER_SIZE MEM_PAGE
void
__twimap_default_reset(struct twimap* map)
return 0;
}
-int
+static int
__twimap_file_read(struct v_inode* inode, void* buf, size_t len, size_t fpos)
{
struct twimap* map = (struct twimap*)(inode->data);
return twimap_read(map, buf, len, fpos);
}
+static int
+__twimap_file_read_page(struct v_inode* inode, void* buf, size_t fpos)
+{
+ return __twimap_file_read(inode, buf, MEM_PAGE, fpos);
+}
+
int
twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos)
{
char* buf = mapping->buffer + mapping->size_acc;
- mapping->size_acc +=
- ksnprintfv(buf, fmt, TWIMAP_BUFFER_SIZE, args) - 1;
+ mapping->size_acc += ksnprintfv(buf, fmt, TWIMAP_BUFFER_SIZE, args) - 1;
va_end(args);
}
struct v_file_ops twimap_file_ops = { .close = default_file_close,
.read = __twimap_file_read,
- .read_page = __twimap_file_read,
+ .read_page = __twimap_file_read_page,
.readdir = default_file_readdir,
.seek = default_file_seek,
.write = default_file_write };
\ No newline at end of file
tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
lxconsole_init();
- /* Get platform configuration */
- acpi_init();
+ device_sysconf_load();
/* Get intc online, this is the cornerstone when initing devices */
intc_init();
+ clock_init();
+ timer_init();
+
/*
TODO autoload these init function that do not have dependency between
them
block_init();
sched_init();
- device_earlystage();
-
- /* System timing and clock support */
- /*
- FIXME we must get timer as earlier as possible
-
- A decoupling between rtc and general device sub-sys is needed.
- Otherwise we timer can only be loaded after device_earlystage.
-
- We need a dedicated timer&clock subsystem
- */
- timer_init();
+ device_onbooot_load();
/* the bare metal are now happy, let's get software over with */
panickf("Fail to mount root. (errno=%d)", errno);
}
- /* Mount these system-wide pseudo-fs */
- vfs_mount("/dev", "devfs", NULL, 0);
- vfs_mount("/sys", "twifs", NULL, MNT_RO);
- vfs_mount("/task", "taskfs", NULL, MNT_RO);
-
/* Finish up bootstrapping sequence, we are ready to spawn the root process
* and start geting into uspace
*/
#include "kp_records.h"
struct kp_records*
-kp_rec_create(int max_recs)
+kprec_create(int max_recs)
{
struct kp_records* recs = (struct kp_records*)valloc(KP_RECS_SIZE);
}
static inline int
-kp_recs_full(struct kp_records* recs)
+kprecs_full(struct kp_records* recs)
{
return recs->cur_recs >= recs->max_recs;
}
-void
-kp_rec_put(struct kp_records* recs, int lvl, char* content, size_t len)
+struct kp_entry*
+kprec_put(struct kp_records* recs, int lvl, char* content, size_t len)
{
assert(len < 256);
struct kp_entry* ent;
- if (!kp_recs_full(recs)) {
+ if (!kprecs_full(recs)) {
assert(recs->kp_ent_wp == &recs->kp_ents.ents);
ent = (struct kp_entry*)vzalloc(KP_ENT_SIZE);
ent->lvl = lvl;
ent->content = _content;
ent->time = clock_systime();
+
+ return ent;
}
\ No newline at end of file
#define KP_RECS_SIZE sizeof(struct kp_records)
struct kp_records*
-kp_rec_create(int max_recs);
+kprec_create(int max_recs);
-void
-kp_rec_put(struct kp_records*, int lvl, char* content, size_t len);
+struct kp_entry*
+kprec_put(struct kp_records*, int lvl, char* content, size_t len);
#endif /* __LUNAIX_KP_RECORDS_H */
#include <lunaix/syscall.h>
#include <lunaix/syslog.h>
+#include <lunaix/lxconsole.h>
+
#include <klibc/strfmt.h>
#include "kp_records.h"
return str;
}
-static void
-__kprintf_level(const char* component, int level, const char* fmt, va_list args)
+static inline void
+kprintf_ml(const char* component, int level, const char* fmt, va_list args)
{
char* buf = &tmp_buf[MAX_BUFSZ_HLF];
ksnprintf(buf, MAX_BUFSZ_HLF, "%s: %s", component, fmt);
size_t sz = ksnprintfv(tmp_buf, buf, MAX_BUFSZ_HLF, args);
- kp_rec_put(&kprecs, level, tmp_buf, sz);
+ kprec_put(&kprecs, level, tmp_buf, sz);
+
+ // FIXME temp measure, get some output
+ console_write_str(tmp_buf);
+ console_write_char('\n');
}
void
-__kprintf(const char* component, const char* fmt, va_list args)
+kprintf_m(const char* component, const char* fmt, va_list args)
{
int level;
fmt = shift_level(fmt, &level);
- __kprintf_level(component, level, fmt, args);
+ kprintf_ml(component, level, fmt, args);
}
static void
struct kp_entry *pos, *n;
llist_for_each(pos, n, kprecs->kp_ent_wp, ents)
{
- twimap_printf(map, "[%05d] %s\n", pos->time, pos->content);
+ time_t s = pos->time / 1000;
+ time_t ms = pos->time % 1000;
+ twimap_printf(map, "[%05d.%03d] %s\n", s, ms, pos->content);
}
}
__DEFINE_LXSYSCALL3(void, syslog, int, level, const char*, fmt, va_list, args)
{
- __kprintf_level("syslog", level, fmt, args);
+ kprintf_ml("syslog", level, fmt, args);
}
\ No newline at end of file
size_t offset = mapping.va - region->start + region->foff;
struct v_inode* inode = region->mfile->inode;
- region->mfile->ops->write_page(
- inode, (void*)mapping.va, PG_SIZE, offset);
+ region->mfile->ops->write_page(inode, (void*)mapping.va, offset);
*mapping.pte &= ~PG_DIRTY;
int errno = 0;
struct device* dev = probe_boot_medium();
if (!dev) {
- kprintf(KERROR "fail to acquire device. (%d)", errno);
+ ERROR("fail to acquire device. (%d)", errno);
return 0;
}
if ((errno = vfs_mount("/mnt/lunaix-os", "iso9660", dev, 0))) {
- kprintf(KERROR "fail to mount boot medium. (%d)", errno);
+ ERROR("fail to mount boot medium. (%d)", errno);
return 0;
}
fail("should not reach");
fail:
- kprintf(KERROR "fail to load initd. (%d)", errno);
+ ERROR("fail to load initd. (%d)", errno);
return 0;
}
void
init_platform()
{
- device_poststage();
+ device_postboot_load();
twifs_register_plugins();
static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
.read = default_file_read,
- .read_page = default_file_read,
+ .read_page =
+ default_file_read_page,
.write = default_file_write,
- .write_page = default_file_write,
+ .write_page =
+ default_file_write_page,
.readdir = taskfs_readdir,
.seek = default_file_seek };
static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup,
-#include <hal/hwrtc.h>
-#include <hal/hwtimer.h>
#include <lunaix/clock.h>
+#include <lunaix/device.h>
#include <lunaix/fs/twifs.h>
#include <lunaix/spike.h>
time_t
clock_systime()
{
- if (!current_timer) {
+ if (!systimer) {
return 0;
}
ticks_t t = hwtimer_current_systicks();
- return t / current_timer->running_freq;
+ ticks_t tu = systimer->running_freq / 1000;
+ return t / (tu + 1);
}
void
clock_walltime(datetime_t* datetime)
{
- primary_rtc->get_walltime(primary_rtc, datetime);
+ sysrtc->get_walltime(sysrtc, datetime);
+}
+
+void
+clock_init()
+{
+ int idx = 0;
+ struct device_def* pos;
+ foreach_exported_device_of(load_timedev, idx, pos)
+ {
+ if (pos->class.device != DEV_RTC) {
+ continue;
+ }
+
+ pos->init(pos);
+ }
}
\ No newline at end of file
.class = DEVCLASSV(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN, 12),
.init = lxconsole_spawn_ttydev
};
-EXPORT_DEVICE(lxconsole, &lxconsole_def, load_earlystage);
\ No newline at end of file
+EXPORT_DEVICE(lxconsole, &lxconsole_def, load_onboot);
\ No newline at end of file
. = ALIGN(8);
- PROVIDE(__lga_dev_ld_early_start = .);
+ PROVIDE(__lga_dev_ld_kboot_start = .);
- KEEP(*(.lga.devdefs.ld_early));
+ KEEP(*(.lga.devdefs.ld_kboot));
- PROVIDE(__lga_dev_ld_early_end = .);
+ PROVIDE(__lga_dev_ld_kboot_end = .);
/* ---- */
. = ALIGN(8);
- PROVIDE(__lga_dev_ld_aftertimer_start = .);
+ PROVIDE(__lga_dev_ld_sysconf_start = .);
- KEEP(*(.lga.devdefs.ld_aftertimer));
+ KEEP(*(.lga.devdefs.ld_sysconf));
- PROVIDE(__lga_dev_ld_aftertimer_end = .);
+ PROVIDE(__lga_dev_ld_sysconf_end = .);
+
+ /* ---- */
+
+ . = ALIGN(8);
+
+ PROVIDE(__lga_dev_ld_timedev_start = .);
+
+ KEEP(*(.lga.devdefs.ld_timedev));
+
+ PROVIDE(__lga_dev_ld_timedev_end = .);
/* ---- */
-no-shutdown \
-d cpu_reset \
-d trace:ide_dma_cb \
- -d trace:vga_std_write_io \
-vga std,retrace=precise \
-serial telnet::12345,server,nowait\
-drive id=disk,file="machine/disk0.vdi",if=none \
#include <errno.h>
#include <fcntl.h>
#include <lunaix/lunaix.h>
+#include <lunaix/mount.h>
#include <stdio.h>
#include <unistd.h>
+#define must_mount(src, target, fs, opts) \
+ do { \
+ int err = 0; \
+ if ((err = mount(src, target, fs, opts))) { \
+ syslog(2, "mount fs %s to %s failed (%d)\n", fs, target, errno); \
+ return err; \
+ } \
+ } while (0)
+
int
main(int argc, const char** argv)
{
int err = 0;
+ mkdir("/dev");
+ mkdir("/sys");
+ mkdir("/task");
+
+ must_mount(NULL, "/dev", "devfs", 0);
+ must_mount(NULL, "/sys", "twifs", MNT_RO);
+ must_mount(NULL, "/task", "taskfs", MNT_RO);
+
if ((err = open("/dev/tty", 0)) < 0) {
syslog(2, "fail to open tty (%d)\n", errno);
- return 0;
+ return err;
}
if ((err = dup(err)) < 0) {
syslog(2, "fail to setup tty i/o (%d)\n", errno);
- return 0;
+ return err;
}
if ((err = symlink("/usr", "/mnt/lunaix-os/usr"))) {
syslog(2, "symlink /usr:/mnt/lunaix-os/usr (%d)\n", errno);
- return 0;
+ return err;
}
pid_t pid;
printf("shell exit abnormally (%d)", err);
}
- return 0;
+ return err;
}
\ No newline at end of file