From: Minep Date: Sat, 21 Oct 2023 21:40:52 +0000 (+0100) Subject: feat: standard vga support (mode switching, framebuffer remapping) X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/8b8f49b713d64065775fe538232f8639083601bd?ds=inline feat: standard vga support (mode switching, framebuffer remapping) feat: better tty/term abstraction feat: mask on pci device id to allow driver do fussy device matching refactor: the variant field of device id is now to be the instance number chore: clean up and re-formatting --- diff --git a/lunaix-os/.vscode/c_cpp_properties.json b/lunaix-os/.vscode/c_cpp_properties.json index a2de1fb..3718f2b 100644 --- a/lunaix-os/.vscode/c_cpp_properties.json +++ b/lunaix-os/.vscode/c_cpp_properties.json @@ -15,7 +15,7 @@ "-include flags.h" ], "defines": [], - "compilerPath": "${HOME}/opt/cross-compiler/bin/i686-elf-gcc", + "compilerPath": "${HOME}/opt/i686-gcc-12/bin/i686-elf-gcc", "cStandard": "gnu99", "intelliSenseMode": "gcc-x86" } diff --git a/lunaix-os/arch/i386/includes/sys/cpu.h b/lunaix-os/arch/i386/includes/sys/cpu.h index 3289522..78faf38 100644 --- a/lunaix-os/arch/i386/includes/sys/cpu.h +++ b/lunaix-os/arch/i386/includes/sys/cpu.h @@ -89,7 +89,7 @@ cpu_chvmspace(u32_t val) } /** - * @brief Flush TLB + * @brief Flush a certain TLB record * * @return u32_t */ @@ -99,6 +99,10 @@ cpu_flush_page(ptr_t va) asm volatile("invlpg (%0)" ::"r"(va) : "memory"); } +/** + * @brief Flush entire TLB + * + */ static inline void cpu_flush_vmspace() { @@ -125,6 +129,11 @@ cpu_wait() asm("hlt"); } +/** + * @brief Read exeception address + * + * @return ptr_t + */ static inline ptr_t cpu_ldeaddr() { diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 220038a..8794bab 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -31,7 +31,7 @@ #define HBA_CLB_SIZE 1024 #define HBA_MY_IE (HBA_PxINTR_DHR | HBA_PxINTR_TFE | HBA_PxINTR_OF) -#define AHCI_DEVCLASS DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA, 0) +#define AHCI_DEVCLASS DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA) // #define DO_HBA_FULL_RESET @@ -444,10 +444,9 @@ achi_register_ops(struct hba_port* port) 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), + .ident_mask = 0x0, + .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA), .name = "Serial ATA Controller", .init_for = ahci_driver_init } }; -EXPORT_DEVICE(ahci, &ahcidef.devdef, load_on_demand); \ No newline at end of file +EXPORT_DEVICE(ahci, &ahcidef.devdef, load_pci_probe); \ No newline at end of file diff --git a/lunaix-os/hal/char/devnull.c b/lunaix-os/hal/char/devnull.c index 5d0aef5..9806dc0 100644 --- a/lunaix-os/hal/char/devnull.c +++ b/lunaix-os/hal/char/devnull.c @@ -32,18 +32,20 @@ __null_rd(struct device* dev, void* buf, size_t offset, size_t len) static int pdev_nulldev_init(struct device_def* def) { - struct device* devnull = device_addseq(NULL, &def->class, NULL, "null"); + struct device* devnull = device_allocseq(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; + device_register(devnull, &def->class, "null"); + return 0; } static struct device_def devnull_def = { .name = "null", - .class = DEVCLASS(DEVIF_NON, DEVFN_PSEUDO, DEV_BUILTIN, 0), + .class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_NULL, DEV_BUILTIN_NULL), .init = pdev_nulldev_init }; EXPORT_DEVICE(nulldev, &devnull_def, load_earlystage); diff --git a/lunaix-os/hal/char/devzero.c b/lunaix-os/hal/char/devzero.c index cd4a6eb..f579047 100644 --- a/lunaix-os/hal/char/devzero.c +++ b/lunaix-os/hal/char/devzero.c @@ -20,16 +20,18 @@ __zero_rd(struct device* dev, void* buf, size_t offset, size_t len) static int pdev_zerodev_init(struct device_def* def) { - struct device* devzero = device_addseq(NULL, &def->class, NULL, "zero"); + struct device* devzero = device_allocseq(NULL, NULL); devzero->ops.read_page = __zero_rd_pg; devzero->ops.read = __zero_rd; + device_register(devzero, &def->class, "zero"); + return 0; } static struct device_def devzero_def = { .name = "zero", - .class = DEVCLASS(DEVIF_NON, DEVFN_PSEUDO, DEV_BUILTIN, 1), + .class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_ZERO, DEV_BUILTIN_ZERO), .init = pdev_zerodev_init }; EXPORT_DEVICE(zerodev, &devzero_def, load_earlystage); diff --git a/lunaix-os/hal/char/ps2kbd.c b/lunaix-os/hal/char/ps2kbd.c index 7756891..c86350b 100644 --- a/lunaix-os/hal/char/ps2kbd.c +++ b/lunaix-os/hal/char/ps2kbd.c @@ -576,7 +576,7 @@ ps2_issue_dev_cmd(char cmd, u16_t arg) static struct device_def devrtc_i8042kbd = { .name = "i8042 Keyboard", - .class = DEVCLASS(DEVIF_SOC, DEVFN_INPUT, DEV_X86LEGACY, 0), + .class = DEVCLASS(DEVIF_SOC, DEVFN_INPUT, DEV_KBD), .init = ps2_kbd_init }; EXPORT_DEVICE(i8042_kbd, &devrtc_i8042kbd, load_timerstage); diff --git a/lunaix-os/hal/char/serial.c b/lunaix-os/hal/char/serial.c index 9297136..ffe9acb 100644 --- a/lunaix-os/hal/char/serial.c +++ b/lunaix-os/hal/char/serial.c @@ -40,11 +40,11 @@ serial_end_xmit(struct serial_dev* sdev, size_t len) int serial_readone_nowait(struct serial_dev* sdev, u8_t* val) { - mutex_lock(&sdev->lock); + device_lock(sdev->dev); int rd_len = fifo_readone(&sdev->rxbuf, val); - mutex_unlock(&sdev->lock); + device_unlock(sdev->dev); return rd_len; } @@ -52,26 +52,26 @@ serial_readone_nowait(struct serial_dev* sdev, u8_t* val) void serial_readone(struct serial_dev* sdev, u8_t* val) { - mutex_lock(&sdev->lock); + device_lock(sdev->dev); while (!fifo_readone(&sdev->rxbuf, val)) { pwait(&sdev->wq_rxdone); } - mutex_unlock(&sdev->lock); + device_unlock(sdev->dev); } size_t serial_readbuf(struct serial_dev* sdev, u8_t* buf, size_t len) { - mutex_lock(&sdev->lock); + device_lock(sdev->dev); size_t rdlen; while (!(rdlen = fifo_read(&sdev->rxbuf, buf, len))) { pwait(&sdev->wq_rxdone); } - mutex_unlock(&sdev->lock); + device_unlock(sdev->dev); return rdlen; } @@ -79,11 +79,11 @@ serial_readbuf(struct serial_dev* sdev, u8_t* buf, size_t len) int serial_readbuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len) { - mutex_lock(&sdev->lock); + device_lock(sdev->dev); int rdlen = fifo_read(&sdev->rxbuf, buf, len); - mutex_unlock(&sdev->lock); + device_unlock(sdev->dev); return rdlen; } @@ -91,7 +91,7 @@ serial_readbuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len) int serial_writebuf(struct serial_dev* sdev, u8_t* buf, size_t len) { - mutex_lock(&sdev->lock); + device_lock(sdev->dev); if (sdev->write(sdev, buf, len) == RXTX_DONE) { goto done; @@ -101,7 +101,7 @@ serial_writebuf(struct serial_dev* sdev, u8_t* buf, size_t len) done: int rdlen = sdev->wr_len; - mutex_unlock(&sdev->lock); + device_unlock(sdev->dev); return rdlen; } @@ -109,12 +109,12 @@ done: int serial_writebuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len) { - mutex_lock(&sdev->lock); + device_lock(sdev->dev); sdev->write(sdev, buf, len); int rdlen = sdev->wr_len; - mutex_unlock(&sdev->lock); + device_unlock(sdev->dev); return rdlen; } @@ -161,8 +161,7 @@ struct serial_dev* serial_create(struct devclass* class) { struct serial_dev* sdev = valloc(sizeof(struct serial_dev)); - struct device* dev = - device_addseq(NULL, class, sdev, "ttyS%d", serial_idx++); + struct device* dev = device_allocseq(NULL, sdev); dev->ops.read = __serial_read; dev->ops.read_page = __serial_read_page; dev->ops.write = __serial_write; @@ -178,6 +177,9 @@ serial_create(struct devclass* class) llist_append(&serial_devs, &sdev->sdev_list); // llist_init_head(&sdev->cmds); + class->variant++; + device_register(dev, class, "ttyS%d", class->variant); + return sdev; } @@ -187,7 +189,7 @@ serial_get_avilable() struct serial_dev *pos, *n; llist_for_each(pos, n, &serial_devs, sdev_list) { - if (!mutex_on_hold(&pos->lock)) { + if (!device_locked(pos->dev)) { return pos; } } diff --git a/lunaix-os/hal/char/uart/16550_pmio.c b/lunaix-os/hal/char/uart/16550_pmio.c index ed3a618..9910051 100644 --- a/lunaix-os/hal/char/uart/16550_pmio.c +++ b/lunaix-os/hal/char/uart/16550_pmio.c @@ -97,7 +97,7 @@ upiom_init(struct device_def* def) } static struct device_def uart_pmio_def = { - .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_SERIAL, 0), + .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_UART16550), .name = "16550 Generic UART (I/O)", .init = upiom_init }; diff --git a/lunaix-os/hal/gfxa/vga/vga.c b/lunaix-os/hal/gfxa/vga/vga.c new file mode 100644 index 0000000..08bc54b --- /dev/null +++ b/lunaix-os/hal/gfxa/vga/vga.c @@ -0,0 +1,260 @@ +/** + * @file ga_vtm.c + * @author Lunaixsky (lunaxisky@qq.com) + * @brief video graphic adapter - text mode with simpiled ansi color code + * @version 0.1 + * @date 2023-10-06 + * + * @copyright Copyright (c) 2023 + * + */ + +#include +#include +#include +#include + +#include + +#include "vga.h" + +#define ALL_FIELDS -1 + +struct vga* +vga_new_state(ptr_t reg_base, ptr_t fb, ptr_t alloced_fbsz) +{ + struct vga* state = valloc(sizeof(struct vga)); + *state = + (struct vga){ .fb = fb, .fb_sz = alloced_fbsz, .io_off = reg_base }; + + return state; +} + +void +vga_config_rect(struct vga* state, + size_t width, + size_t height, + size_t freq, + int d9) +{ + size_t pel_sz = 8 + !!d9; + + state->crt.h_cclk = width / pel_sz; + state->crt.v_cclk = height; + state->crt.freq = freq; + + state->crt.pel_dot = pel_sz; +} + +#define RETRACE_GAP 4 + +static void +vga_crt_update(struct vga* state) +{ +#define R_BIT9(x, l) ((((x) & (1 << 9)) >> 9) << (l)) +#define R_BIT8(x, l) ((((x) & (1 << 8)) >> 8) << (l)) + struct vga_regops* reg = &state->reg_ops; + + u32_t hdisp = state->crt.h_cclk; + u32_t vdisp = state->crt.v_cclk; + u32_t hdisp_end = hdisp - 1; + u32_t vdisp_end = vdisp - 1; + + // VGA spec said so + u32_t htotal = hdisp - 5; + u32_t vtotal = vdisp - 5; + + u32_t hsync_end = (hdisp + RETRACE_GAP) & 0b11111; + u32_t vsync_end = (vdisp + RETRACE_GAP) & 0b01111; + + reg->write(state, VGA_CRX, VGA_CR11, 0, 1 << 7); + reg->write(state, VGA_CRX, VGA_CR03, 1 << 7, 1 << 7); + + // set values of first 8 registers. Note, we prefer no H_BLANK region + u32_t crt_regs[VGA_CRCOUNT] = { + [VGA_CR00] = htotal, [VGA_CR01] = hdisp - 1, + [VGA_CR02] = 0xff, [VGA_CR03] = (1 << 7) | 31, + [VGA_CR04] = hdisp, [VGA_CR05] = hsync_end, + [VGA_CR06] = vtotal + }; + + // overflow: bit 9/8 of vtotal + crt_regs[VGA_CR07] = R_BIT9(vtotal, 5) | R_BIT8(vtotal, 0); + // overflow: bit 9/8 of vdisp_end + crt_regs[VGA_CR07] |= R_BIT9(vdisp_end, 6) | R_BIT8(vdisp_end, 1); + // overflow: bit 9/8 of vsync_start + crt_regs[VGA_CR07] |= R_BIT9(vdisp, 7) | R_BIT8(vdisp, 2); + + crt_regs[VGA_CR10] = vdisp; // vsync_start + + // V_SYNC_END, Disable Vertical INTR (GD5446) + crt_regs[VGA_CR11] = vsync_end | (1 << 5); + crt_regs[VGA_CR12] = vdisp_end; // vdisp_end + + // no V_BLANK region (v blank start/end = 0x3ff) + crt_regs[VGA_CR15] = 0xff; + crt_regs[VGA_CR16] = 0xff; + crt_regs[VGA_CR09] |= (1 << 5); + crt_regs[VGA_CR07] |= (1 << 3); + + // no split line (0x3FF) + crt_regs[VGA_CR18] = 0xff; + crt_regs[VGA_CR07] |= (1 << 4); + crt_regs[VGA_CR09] |= (1 << 6); + + // disable text cursor by default + crt_regs[VGA_CR0A] = (1 << 5); + // CRB: text cusor end, 0x00 + // CRE-CRF: text cusor location, cleared, 0x00 + + // CRC-CRD: screen start address(lo/hi): 0x00, 0x00 + // i.e., screen content start at the beginning of framebuffer + + if (!(state->options & VGA_MODE_GFX)) { + // AN Mode, each char heights 16 scan lines + crt_regs[VGA_CR09] |= 0xf; + } else { + // GFX Mode, individual scanline, no repeat + } + + // framebuffer: 16bit granule + u32_t divsor = 2 * 2; + if (state->lut.len == 256) { + // if 8 bit color is used, 2 pixels per granule + divsor *= 2; + } else if ((state->options & VGA_MODE_GFX)) { + // otherwise (gfx mode), 4 pixels per granule + divsor *= 4; + } // AN mode, one granule per character + crt_regs[VGA_CR13] = (hdisp * state->crt.pel_dot) / divsor; + + // Timing En, Word Mode, Address Warp, + crt_regs[VGA_CR17] = (0b10100011); + + reg->set_seq(state, VGA_CRX, 0, crt_regs, VGA_CRCOUNT); +} + +void +vga_update_palette(struct vga* state) +{ + state->reg_ops.set_dac_palette(state); + + u32_t index[16]; + u32_t clr_len = MIN(state->lut.len, 16); + for (size_t i = 0; i < clr_len; i++) { + index[i] = i; + } + + state->reg_ops.set_seq(state, VGA_ARX, 0, index, clr_len); +} + +void +vga_reload_config(struct vga* state) +{ + cpu_disable_interrupt(); + + struct vga_regops* reg = &state->reg_ops; + + u32_t color = state->lut.len; + assert_msg((color == 2 || color == 4 || color == 16 || color == 256), + "invalid color depth"); + + if (!(state->options & VGA_MODE_GFX)) { + assert(color < 256); + } + + // estimate actual fb size + u32_t dpc_sq = state->crt.pel_dot; + u32_t total_px = state->crt.h_cclk * state->crt.v_cclk; + if ((state->options & VGA_MODE_GFX)) { + total_px *= dpc_sq; + total_px = total_px / (1 + (color < 256)); + } else { + total_px = total_px * 2; + } + + assert(state->fb_sz >= total_px); + state->fb_sz = total_px; + + reg->write(state, VGA_SRX, VGA_SR00, 0x0, ALL_FIELDS); + + // RAM Enable, I/OAS + u32_t clk_f = state->crt.h_cclk * state->crt.v_cclk * state->crt.freq; + u32_t misc = 0b11; + clk_f = (clk_f * dpc_sq) / 1000000; + + assert(clk_f && clk_f <= 28); + + // require 28 MHz clock + if (clk_f > 25) { + misc |= 0b01 << 2; + } + // 25 MHz clock: 0b00 << 2 + + reg->write(state, VGA_MISCX, 0, misc, 0b1111); + + // SEQN_CLK: shift every CCLK, DCLK passthrough, 8/9 DCLK + u32_t d89 = (state->crt.pel_dot != 9); + reg->write(state, VGA_SRX, VGA_SR01, d89, ALL_FIELDS); + + // GR0-4 + u32_t gr_regs[] = { 0, 0, 0, 0, 0 }; + reg->set_seq(state, VGA_GRX, 0, gr_regs, 5); + + // Setup CRT + vga_crt_update(state); + + if ((state->options & VGA_MODE_GFX)) { // GFX MODE + // GFX mode, check if 8 bit color depth is required + u32_t c256 = (color == 256); + reg->write(state, VGA_ARX, VGA_AR10, 1 | (c256 << 6), ALL_FIELDS); + + // All 4 maps enabled, chain 4 mode + reg->write(state, VGA_SRX, VGA_SR02, 0b1111, ALL_FIELDS); + + // Chain-4, Odd/Even, Extended Memory + reg->write(state, VGA_SRX, VGA_SR04, 0b1010, ALL_FIELDS); + + // check 256 color mode, RdM0, WrM0 + reg->write( + state, VGA_GRX, VGA_GR05, (c256 << 6) | (1 << 4), ALL_FIELDS); + + // Legacy GFX FB: 0xA000, GFX mode + reg->write(state, VGA_GRX, VGA_GR06, 0b0011, ALL_FIELDS); + + } else { // AN MOODE + // Only map 0,1 enabled, (ascii and attribute) + reg->write(state, VGA_SRX, VGA_SR02, 0b0011, ALL_FIELDS); + + // Character (AN) mode + reg->write(state, VGA_ARX, VGA_AR10, 0, ALL_FIELDS); + + // Extended Memory + reg->write(state, VGA_SRX, VGA_SR04, 0b0010, ALL_FIELDS); + + // Shift Reg, RdM0, WrM0 + reg->write(state, VGA_GRX, VGA_GR05, (1 << 5), ALL_FIELDS); + + // Legacy CGA FB: 0xB800, AN mode + reg->write(state, VGA_GRX, VGA_GR06, 0b1100, 0b1111); + } + + // all planes not involved in color compare + reg->write(state, VGA_GRX, VGA_GR07, 0, ALL_FIELDS); + // No rotate, no bit ops with latched px + reg->write(state, VGA_GRX, VGA_GR03, 0, ALL_FIELDS); + + // Load default bit mask + reg->write(state, VGA_GRX, VGA_GR08, 0xff, ALL_FIELDS); + + reg->write(state, VGA_ARX, VGA_AR12, 0xf, ALL_FIELDS); + reg->write(state, VGA_ARX, VGA_AR11, 0b100, ALL_FIELDS); + reg->write(state, VGA_ARX, VGA_AR13, 0, ALL_FIELDS); + reg->write(state, VGA_ARX, VGA_AR14, 0, ALL_FIELDS); + + vga_update_palette(state); + + reg->write(state, VGA_SRX, VGA_SR00, 0x3, ALL_FIELDS); + + cpu_enable_interrupt(); +} diff --git a/lunaix-os/hal/gfxa/vga/vga.h b/lunaix-os/hal/gfxa/vga/vga.h new file mode 100644 index 0000000..86afe4e --- /dev/null +++ b/lunaix-os/hal/gfxa/vga/vga.h @@ -0,0 +1,232 @@ +#ifndef __LUNAIX_VGA_H +#define __LUNAIX_VGA_H + +#include + +/* -- Attribute Controller -- */ + +#define VGA_ARX 0 +// Attribute Mode Control Register +#define VGA_AR10 0x10 + +// Overscan Color Register +#define VGA_AR11 0x11 + +// Color Plane Enable Register +#define VGA_AR12 0x12 + +// Horizontal Pixel Panning Register +#define VGA_AR13 0x13 + +// Color Select Register +#define VGA_AR14 0x14 + +/* -- Sequencer -- */ + +#define VGA_SRX 1 +// Reset Register +#define VGA_SR00 0x00 + +// Clocking Mode Register +#define VGA_SR01 0x01 + +// Map Mask Register +#define VGA_SR02 0x02 + +// Character Map Select Register +#define VGA_SR03 0x03 + +// Sequencer Memory Mode Register +#define VGA_SR04 0x04 + +/* -- GFX Controller -- */ + +#define VGA_GRX 2 +// Set/Reset Register +#define VGA_GR00 0x00 + +// Enable Set/Reset Register +#define VGA_GR01 0x01 + +// Color Compare Register +#define VGA_GR02 0x02 + +// Data Rotate Register +#define VGA_GR03 0x03 + +// Read Map Select Register +#define VGA_GR04 0x04 + +// Graphics Mode Register +#define VGA_GR05 0x05 + +// Miscellaneous Graphics Register +#define VGA_GR06 0x06 + +// Color Don't Care Register +#define VGA_GR07 0x07 + +// Bit Mask Register +#define VGA_GR08 0x08 + +/* -- CRT Controller -- */ + +#define VGA_CRX 3 + +// Horizontal Total Register +#define VGA_CR00 0x00 + +// End Horizontal Display Register +#define VGA_CR01 0x01 + +// Start Horizontal Blanking Register +#define VGA_CR02 0x02 + +// End Horizontal Blanking Register +#define VGA_CR03 0x03 + +// Start Horizontal Retrace Register +#define VGA_CR04 0x04 + +// End Horizontal Retrace Register +#define VGA_CR05 0x05 + +// Vertical Total Register +#define VGA_CR06 0x06 + +// Overflow Register +#define VGA_CR07 0x07 + +// Preset Row Scan Register +#define VGA_CR08 0x08 + +// Maximum Scan Line Register +#define VGA_CR09 0x09 + +// Cursor Start Register +#define VGA_CR0A 0x0A + +// Cursor End Register +#define VGA_CR0B 0x0B + +// Start Address High Register +#define VGA_CR0C 0x0C + +// Start Address Low Register +#define VGA_CR0D 0x0D + +// Cursor Location High Register +#define VGA_CR0E 0x0E + +// Cursor Location Low Register +#define VGA_CR0F 0x0F + +// Vertical Retrace Start Register +#define VGA_CR10 0x10 + +// Vertical Retrace End Register +#define VGA_CR11 0x11 + +// Vertical Display End Register +#define VGA_CR12 0x12 + +// Offset Register +#define VGA_CR13 0x13 + +// Underline Location Register +#define VGA_CR14 0x14 + +// Start Vertical Blanking Register +#define VGA_CR15 0x15 + +// End Vertical Blanking +#define VGA_CR16 0x16 + +// CRTC Mode Control Register +#define VGA_CR17 0x17 + +// Line Compare Register +#define VGA_CR18 0x18 +#define VGA_CRCOUNT 0x19 + +/* -- Digital-Analogue Converter -- */ + +// DAC register +#define VGA_DACX 4 + +// DAC Data Register +#define VGA_DAC1 0x3C9 + +// DAC State Register +#define VGA_DAC2 0x3C7 + +#define VGA_MISCX 5 +#define VGA_STATX 6 + +#define VGA_REG_X 0 +#define VGA_REG_D 1 + +#define VGA_MODE_GFX (0b0001) + +struct vga; + +struct vga_regops +{ + u32_t (*read)(struct vga*, u32_t type, u32_t index, u32_t mask); + void (*write)(struct vga*, u32_t type, u32_t index, u32_t val, u32_t mask); + void ( + *set_seq)(struct vga*, u32_t type, size_t off, u32_t* seq, size_t len); + void (*set_dac_palette)(struct vga*); +}; + +struct vga +{ + ptr_t io_off; + ptr_t fb; + size_t fb_sz; + u32_t options; + + struct + { + size_t h_cclk; // horizontal char clock count; + size_t v_cclk; // vertical char clock count; + size_t pel_dot; // pixel per dot clock + size_t freq; + size_t fb_off; + } crt; + + struct + { + u32_t* colors; + u32_t len; + } lut; + + struct vga_regops reg_ops; +}; + +/** + * @brief Create a new VGA state + * + * @param reg_base base address for register accessing + * @param fb address to frame buffer + * @param fb_sz size of usable frame buffer + * @return struct vga* VGA state + */ +struct vga* +vga_new_state(ptr_t reg_base, ptr_t fb, ptr_t fb_sz); + +/** + * @brief Config VGA active displaying region dimension (resolution) + * + * @param width width in pixel counts + * @param hight height in pixel counts + * @param freq frame update frequency + * @param d9 use D9 character clock + */ +void +vga_config_rect(struct vga*, size_t width, size_t hight, size_t freq, int d9); + +void +vga_reload_config(struct vga*); + +#endif /* __LUNAIX_VGA_H */ diff --git a/lunaix-os/hal/gfxa/vga/vga_mmio_ops.c b/lunaix-os/hal/gfxa/vga/vga_mmio_ops.c new file mode 100644 index 0000000..4ec8c3e --- /dev/null +++ b/lunaix-os/hal/gfxa/vga/vga_mmio_ops.c @@ -0,0 +1,90 @@ +#include "vga.h" + +typedef volatile u8_t vga_reg8; + +#define regaddr(type, i, vga) \ + ((vga_reg8*)(vga_gfx_regmap[type][i] + (vga)->io_off)) + +#define arx_reset(v) (void)(*regaddr(VGA_STATX, 1, v)) + +// Port IO Address - 0x3C0 +static u32_t vga_gfx_regmap[][2] = { + [VGA_ARX] = { 0x0, 0x1 }, [VGA_SRX] = { 0x04, 0x05 }, + [VGA_GRX] = { 0x0E, 0x0F }, [VGA_CRX] = { 0x14, 0x15 }, + [VGA_DACX] = { 0x08, 0x09 }, [VGA_MISCX] = { 0x02, 0x0C }, + [VGA_STATX] = { 0x02, 0x1A } +}; + +static u32_t +vga_mmio_read(struct vga* v, u32_t type, u32_t index, u32_t mask) +{ + vga_reg8* reg_ix = regaddr(type, VGA_REG_X, v); + vga_reg8* reg_rd = regaddr(type, VGA_REG_D, v); + *reg_ix = (u8_t)index; + return ((u32_t)*reg_rd) & mask; +} + +static void +vga_mmio_write(struct vga* v, u32_t type, u32_t index, u32_t val, u32_t mask) +{ + index = index & 0xff; + val = val & mask; + vga_reg8* reg_ix = regaddr(type, VGA_REG_X, v); + if (type == VGA_ARX) { + // reset ARX filp-flop + arx_reset(v); + *reg_ix = ((u8_t)index) | 0x20; + *reg_ix = val; + return; + } else if (type == VGA_MISCX) { + *reg_ix = val; + return; + } + + *((u16_t*)reg_ix) = (u16_t)(((val) << 8) | index); +} + +static void +vga_mmio_set_regs(struct vga* v, u32_t type, size_t off, u32_t* seq, size_t len) +{ + vga_reg8* reg_ix = regaddr(type, VGA_REG_X, v); + if (type == VGA_ARX) { + arx_reset(v); + for (size_t i = 0; i < len; i++) { + *reg_ix = (u8_t)(off + i) | 0x20; + *reg_ix = seq[i]; + } + + } else { + for (size_t i = 0; i < len; i++) { + *((u16_t*)reg_ix) = (u16_t)((seq[i] << 8) | ((off + i) & 0xff)); + } + } +} + +static void +vga_mmio_set_dacp(struct vga* v) +{ +#define R(c) (u8_t)(((c) & 0xff0000) >> 16) +#define G(c) (u8_t)(((c) & 0x00ff00) >> 8) +#define B(c) (u8_t)(((c) & 0x0000ff)) + + vga_reg8* reg_ix = regaddr(VGA_DACX, VGA_REG_X, v); + vga_reg8* reg_dat = regaddr(VGA_DACX, VGA_REG_D, v); + + u32_t* color_map = v->lut.colors; + + *reg_ix = 0; + for (size_t i = 0; i < v->lut.len; i++) { + u32_t color = color_map[i]; + *reg_dat = R(color); + *reg_dat = G(color); + *reg_dat = B(color); + } +} + +struct vga_regops vga_default_mmio_ops = { .read = vga_mmio_read, + .write = vga_mmio_write, + .set_seq = vga_mmio_set_regs, + .set_dac_palette = + vga_mmio_set_dacp }; \ No newline at end of file diff --git a/lunaix-os/hal/gfxa/vga/vga_pci.c b/lunaix-os/hal/gfxa/vga/vga_pci.c new file mode 100644 index 0000000..baf7fa4 --- /dev/null +++ b/lunaix-os/hal/gfxa/vga/vga_pci.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "vga.h" + +extern struct vga_regops vga_default_mmio_ops; + +#define FB256K 256 << 10 + +static u32_t palette[] = { + 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, + 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, + 0x00ffff, 0xffffff, 0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, + 0x0000ff, 0x005f00, 0x005f5f, 0x005f87, 0x005faf, 0x005fd7, 0x005fff, + 0x008700, 0x00875f, 0x008787, 0x0087af, 0x0087d7, 0x0087ff, 0x00af00, + 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff, 0x00d700, 0x00d75f, + 0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f, 0x00ff87, + 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af, + 0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, 0x5f5f87, 0x5f5faf, 0x5f5fd7, + 0x5f5fff, 0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, + 0x5faf00, 0x5faf5f, 0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, + 0x5fd75f, 0x5fd787, 0x5fd7af, 0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, + 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff, 0x870000, 0x87005f, 0x870087, + 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f, 0x875f87, 0x875faf, + 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af, 0x8787d7, + 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff, + 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, + 0x87ff5f, 0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, + 0xaf0087, 0xaf00af, 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, + 0xaf5faf, 0xaf5fd7, 0xaf5fff, 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, + 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f, 0xafaf87, 0xafafaf, 0xafafd7, + 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af, 0xafd7d7, 0xafd7ff, + 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff, 0xd70000, + 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f, + 0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, + 0xd787af, 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, + 0xd7afd7, 0xd7afff, 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, + 0xd7d7ff, 0xd7ff00, 0xd7ff5f, 0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, + 0xff0000, 0xff005f, 0xff0087, 0xff00af, 0xff00d7, 0xff00ff, 0xff5f00, + 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff, 0xff8700, 0xff875f, + 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f, 0xffaf87, + 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af, + 0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, + 0xffffff, 0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, + 0x444444, 0x4e4e4e, 0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, + 0x8a8a8a, 0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, + 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee +}; + +#define VGA_REG_OFF 0x0400 + +static int +vga_pci_init(struct device_def* devdef, struct device* pcidev_base) +{ + struct pci_device* pcidev = PCI_DEVICE(pcidev_base); + + struct pci_base_addr* fb = &pcidev->bar[0]; + struct pci_base_addr* mmio = &pcidev->bar[2]; + + if (PCI_BAR_ADDR_IO(mmio->type)) { + return EINVAL; + } + + pci_reg_t cmd = pci_read_cspace(pcidev->cspace_base, PCI_REG_STATUS_CMD); + + cmd |= (PCI_RCMD_MM_ACCESS | PCI_RCMD_DISABLE_INTR | PCI_RCMD_BUS_MASTER); + + pci_write_cspace(pcidev->cspace_base, PCI_REG_STATUS_CMD, cmd); + + ptr_t fb_mapped = (ptr_t)ioremap(fb->start, FB256K); + ptr_t mmio_mapped = (ptr_t)ioremap(mmio->start, mmio->size); + + struct vga* vga_state = + vga_new_state(mmio_mapped + VGA_REG_OFF, fb_mapped, FB256K); + vga_state->reg_ops = vga_default_mmio_ops; + vga_state->lut.colors = palette; + vga_state->lut.len = 256; + vga_state->options = VGA_MODE_GFX; + + vga_config_rect(vga_state, 640, 360, 60, 0); + + // TEMP: Test the change of VGA display mode and resolution + // vga_reload_config(vga_state); + + return 0; +} + +#define VGA_PCI_CLASS 0x30000 + +static struct pci_device_def vga_pci_devdef = { + .dev_class = VGA_PCI_CLASS, + .dev_ident = PCI_DEVIDENT(0x1234, 0x1111), + .ident_mask = -1, + .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_DISP, DEV_VGA), + .name = "VGA Generic Driver", + .init_for = vga_pci_init } +}; +EXPORT_DEVICE(vga_pci, &vga_pci_devdef.devdef, load_pci_probe); \ No newline at end of file diff --git a/lunaix-os/hal/gfxa/vga/vga_pmio_ops.c b/lunaix-os/hal/gfxa/vga/vga_pmio_ops.c new file mode 100644 index 0000000..7ad90fc --- /dev/null +++ b/lunaix-os/hal/gfxa/vga/vga_pmio_ops.c @@ -0,0 +1,9 @@ +#include "vga.h" + +static u32_t vga_gfx_regmap[][2] = { + [VGA_ARX] = { 0x3C0, 0x3C1 }, [VGA_SRX] = { 0x3C4, 0x3C5 }, + [VGA_GRX] = { 0x3CE, 0x3CF }, [VGA_CRX] = { 0x3D4, 0x3D5 }, + [VGA_DACX] = { 0x3C8, 0x3C9 }, [VGA_MISCX] = { 0x3CC, 0x3C2 } +}; + +// TODO \ No newline at end of file diff --git a/lunaix-os/hal/pci.c b/lunaix-os/hal/pci.c index 3859e0c..7a1967e 100644 --- a/lunaix-os/hal/pci.c +++ b/lunaix-os/hal/pci.c @@ -21,6 +21,8 @@ LOG_MODULE("PCI") static DEFINE_LLIST(pci_devices); +static struct device* pcidev_cat; + void pci_probe_msi_info(struct pci_device* device); @@ -42,8 +44,8 @@ pci_create_device(ptr_t pci_base, int devinfo) continue; } - int result = (pos->dev_vendor & vendor) == vendor && - (pos->dev_id & devid) == devid; + u32_t idm = pos->ident_mask; + int result = (pos->dev_ident & idm) == (devinfo & idm); if (result) { goto found; @@ -63,14 +65,14 @@ found: device->cspace_base = pci_base; device->intr_info = intr; - device_prepare(&device->dev, &pos->devdef.class); + device_create(&device->dev, pcidev_cat, DEV_IFSYS, NULL); 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.fn_grp, pos->devdef.class.device, pos->devdef.class.variant); @@ -86,6 +88,7 @@ found: } llist_append(&pci_devices, &device->dev_chain); + device_register(&device->dev, &pos->devdef.class, "%x:%x", vendor, devid); return device; @@ -338,6 +341,8 @@ EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping); static int pci_load_devices(struct device_def* def) { + pcidev_cat = device_addcat(NULL, "pci"); + pci_scan(); return 0; @@ -345,7 +350,7 @@ pci_load_devices(struct device_def* def) static struct device_def pci_def = { .name = "pci3.0-hba", - .class = DEVCLASS(DEVIF_SOC, DEVFN_BUSIF, DEV_BUS, 0), + .class = DEVCLASS(DEVIF_SOC, DEVFN_BUSIF, DEV_PCI), .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 f398c66..3035f31 100644 --- a/lunaix-os/hal/rng/rngx86.c +++ b/lunaix-os/hal/rng/rngx86.c @@ -31,16 +31,18 @@ __rand_rd(struct device* dev, void* buf, size_t offset, size_t len) int pdev_randdev_init(struct device_def* devdef) { - struct device* devrand = device_addseq(NULL, &devdef->class, NULL, "rand"); + struct device* devrand = device_allocseq(NULL, NULL); devrand->ops.read = __rand_rd; devrand->ops.read_page = __rand_rd_pg; + device_register(devrand, &devdef->class, "rand"); + return 0; } static struct device_def devrandx86_def = { .name = "x86 On-Chip RNG", - .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_RNG, 0), + .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 diff --git a/lunaix-os/hal/rtc/hwrtc.c b/lunaix-os/hal/rtc/hwrtc.c index 82f98eb..87e7d10 100644 --- a/lunaix-os/hal/rtc/hwrtc.c +++ b/lunaix-os/hal/rtc/hwrtc.c @@ -84,15 +84,16 @@ hwrtc_alloc_new(struct device_def* def, char* name) } rtc_instance->name = name; - struct device* rtcdev = - device_addsys(NULL, &def->class, rtc_instance, "rtc%d", rtc_count); + struct device* rtcdev = device_allocsys(NULL, rtc_instance); rtcdev->ops.exec_cmd = hwrtc_ioctl; rtcdev->ops.read = hwrtc_read; rtc_instance->rtc_dev = rtcdev; - rtc_count++; + device_register(rtcdev, &def->class, "rtc%d", def->class.variant); + + def->class.variant++; return rtc_instance; } diff --git a/lunaix-os/hal/rtc/mc146818a.c b/lunaix-os/hal/rtc/mc146818a.c index dce0a51..6b64527 100644 --- a/lunaix-os/hal/rtc/mc146818a.c +++ b/lunaix-os/hal/rtc/mc146818a.c @@ -217,7 +217,7 @@ rtc_init(struct device_def* devdef) static struct device_def devrtc_mc146818 = { .name = "MC146818 RTC", - .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC, 1), + .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC), .init = rtc_init }; EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_earlystage); \ No newline at end of file diff --git a/lunaix-os/hal/term/lcntls/ansi_cntl.c b/lunaix-os/hal/term/lcntls/ansi_cntl.c new file mode 100644 index 0000000..a11781e --- /dev/null +++ b/lunaix-os/hal/term/lcntls/ansi_cntl.c @@ -0,0 +1,57 @@ +#include + +#include + +#define CTRL_MNEMO(chr) (chr - 'A' + 1) + +static inline int +__ansi_actcontrol(struct term* termdev, char chr) +{ + struct linebuffer* lbuf = &termdev->line; + switch (chr) { + case '\0': // EOL + case CTRL_MNEMO('D'): // EOF + return 0; + + case CTRL_MNEMO('C'): // INTR + signal_send(termdev->fggrp, SIGINT); + break; + + case '\r': // CR + termdev->line.ptr = 0; + return 1; + + case '\x08': // ERASE + return line_put_next(lbuf, chr, -1); + + case CTRL_MNEMO('Q'): // QUIT + signal_send(termdev->fggrp, SIGKILL); + return 1; + + case CTRL_MNEMO('Z'): // SUSP + signal_send(termdev->fggrp, SIGSTOP); + return 1; + + default: + if ((int)chr < 32) { + line_put_next(lbuf, '^', 0); + chr += 64; + } + break; + } + + return line_put_next(lbuf, chr, 0); +} + +static size_t +ansi_lcntl_process(struct term* termdev, char* line, size_t len) +{ + size_t i = 0; + while (i < len && __ansi_actcontrol(termdev, line[i])) { + i++; + } + + return i; +} + +struct term_lcntl ansi_line_controller = { .apply = ansi_lcntl_process }; \ No newline at end of file diff --git a/lunaix-os/hal/term/term.c b/lunaix-os/hal/term/term.c new file mode 100644 index 0000000..2130105 --- /dev/null +++ b/lunaix-os/hal/term/term.c @@ -0,0 +1,312 @@ +#include +#include +#include +#include +#include +#include + +#include + +#define ANSI_LCNTL 0 + +extern struct term_lcntl ansi_line_controller; +static struct term_lcntl* line_controls[] = { [ANSI_LCNTL] = + &ansi_line_controller }; +#define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*)) + +static int +term_exec_cmd(struct device* dev, u32_t req, va_list args) +{ + struct term* term = (struct term*)dev->underlay; + int err = 0; + + device_lock(dev); + + switch (req) { + case TIOCSPGRP: { + pid_t pgid = va_arg(args, pid_t); + if (pgid < 0) { + err = EINVAL; + goto done; + } + term->fggrp = pgid; + break; + } + case TIOCGPGRP: + return term->fggrp; + case TIOCPUSH: { + u32_t lcntl_idx = va_arg(args, u32_t); + struct term_lcntl* lcntl = term_get_lcntl(lcntl_idx); + + if (!lcntl) { + err = EINVAL; + goto done; + } + + term_push_lcntl(term, lcntl); + break; + } + case TIOCPOP: + term_pop_lcntl(term); + break; + case TIOCSCDEV: { + int fd = va_arg(args, int); + struct v_fd* vfd; + + if (vfs_getfd(fd, &vfd)) { + err = EINVAL; + goto done; + } + + struct device* cdev = device_cast(vfd->file->inode->data); + if (!cdev) { + err = ENOTDEV; + goto done; + } + if (cdev->dev_type != DEV_IFSEQ) { + err = EINVAL; + goto done; + } + + term_bind(term, cdev); + break; + } + case TIOCGCDEV: { + struct dev_info* devinfo = va_arg(args, struct dev_info*); + + if (!term->chdev) { + err = ENODEV; + goto done; + } + + if (devinfo) { + device_populate_info(term->chdev, devinfo); + } + break; + } + default: + err = EINVAL; + goto done; + } + +done: + device_unlock(dev); + return err; +} + +static int +term_write(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct term* term = (struct term*)dev->underlay; + size_t sz = MIN(len, term->line.sz_hlf); + + if (!term->chdev) { + return ENODEV; + } + + device_lock(term->dev); + + memcpy(term->line.current, &((char*)buf)[offset], sz); + + struct term_lcntl *lcntl, *n; + llist_for_each(lcntl, n, &term->lcntl_stack, lcntls) + { + sz = lcntl->apply(term, term->line.current, sz); + line_flip(&term->line); + } + + int errcode = term_sendline(term, sz); + + device_unlock(term->dev); + + return errcode; +} + +static int +term_read(struct device* dev, void* buf, size_t offset, size_t len) +{ + struct term* term = (struct term*)dev->underlay; + size_t sz = MIN(len, term->line.sz_hlf); + + if (!term->chdev) { + return ENODEV; + } + + device_lock(term->dev); + + sz = term_readline(term, sz); + if (!sz) { + device_unlock(term->dev); + return 0; + } + + struct term_lcntl *pos, *n; + llist_for_each(pos, n, &term->lcntl_stack, lcntls) + { + sz = pos->apply(term, term->line.current, sz); + line_flip(&term->line); + } + + memcpy(&((char*)buf)[offset], term->line.current, sz); + + device_unlock(term->dev); + + return sz; +} + +struct term* +term_create() +{ + struct term* terminal = valloc(sizeof(struct term)); + + if (!terminal) { + return NULL; + } + + terminal->dev = device_allocseq(NULL, terminal); + + terminal->dev->ops.read = term_read; + terminal->dev->ops.write = term_write; + + llist_init_head(&terminal->lcntl_stack); + line_alloc(&terminal->line, 1024); + + return terminal; +} + +int +term_bind(struct term* term, struct device* chdev) +{ + device_lock(term->dev); + + term->chdev = chdev; + + device_unlock(term->dev); + + return 0; +} + +struct term_lcntl* +term_get_lcntl(u32_t lcntl_index) +{ + if (lcntl_index >= LCNTL_TABLE_LEN) { + return NULL; + } + + struct term_lcntl* lcntl_template = line_controls[lcntl_index]; + struct term_lcntl* lcntl_instance = valloc(sizeof(struct term_lcntl)); + + if (!lcntl_instance) { + return NULL; + } + + lcntl_instance->apply = lcntl_template->apply; + + return lcntl_instance; +} + +int +term_push_lcntl(struct term* term, struct term_lcntl* lcntl) +{ + device_lock(term->dev); + + llist_append(&term->lcntl_stack, &lcntl->lcntls); + + device_unlock(term->dev); + + return 0; +} + +int +term_pop_lcntl(struct term* term) +{ + if (term->lcntl_stack.prev == &term->lcntl_stack) { + return 0; + } + + device_lock(term->dev); + + struct term_lcntl* lcntl = + list_entry(term->lcntl_stack.prev, struct term_lcntl, lcntls); + llist_delete(term->lcntl_stack.prev); + + vfree(lcntl); + + device_unlock(term->dev); + + return 1; +} + +void +line_flip(struct linebuffer* lbf) +{ + char* tmp = lbf->current; + lbf->current = lbf->next; + lbf->next = tmp; +} + +void +line_alloc(struct linebuffer* lbf, size_t sz_hlf) +{ + char* buffer = valloc(sz_hlf * 2); + lbf->current = buffer; + lbf->next = &buffer[sz_hlf]; + lbf->sz_hlf = sz_hlf; +} + +void +line_free(struct linebuffer* lbf, size_t sz_hlf) +{ + void* ptr = (void*)MIN((ptr_t)lbf->current, (ptr_t)lbf->next); + vfree(ptr); +} + +int +term_sendline(struct term* tdev, size_t len) +{ + struct device* chdev = tdev->chdev; + + device_lock(chdev); + + int code = chdev->ops.write(chdev, tdev->line.current, 0, len); + + device_unlock(chdev); + + return code; +} + +int +term_readline(struct term* tdev, size_t len) +{ + struct device* chdev = tdev->chdev; + + device_lock(chdev); + + int code = chdev->ops.read(chdev, tdev->line.current, 0, len); + + device_unlock(chdev); + + return code; +} + +int +term_init(struct device_def* devdef) +{ + struct term* terminal = term_create(); + struct device* tdev = device_allocseq(NULL, terminal); + tdev->ops.read = term_read; + tdev->ops.write = term_write; + tdev->ops.exec_cmd = term_exec_cmd; + + devdef->class.variant++; + device_register(tdev, &devdef->class, "tty%d", devdef->class.variant); + + return 0; +} + +static struct device_def vterm_def = { + .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM), + .name = "virtual terminal", + .init = term_init +}; +EXPORT_DEVICE(vterm, &vterm_def, load_on_demand); \ No newline at end of file diff --git a/lunaix-os/hal/timer/apic_timer.c b/lunaix-os/hal/timer/apic_timer.c index c52cebe..e195f34 100644 --- a/lunaix-os/hal/timer/apic_timer.c +++ b/lunaix-os/hal/timer/apic_timer.c @@ -150,12 +150,13 @@ apic_timer_init(struct hwtimer* timer, u32_t hertz, timer_tick_cb timer_cb) struct hwtimer* apic_hwtimer_context() { - static struct hwtimer apic_hwt = { .name = "apic_timer", - .class = DEVCLASS( - DEVIF_SOC, DEVFN_TIME, DEV_TIMER, 0), - .init = apic_timer_init, - .supported = apic_timer_check, - .systicks = apic_get_systicks }; + static struct hwtimer apic_hwt = { + .name = "apic_timer", + .class = DEVCLASSV(DEVIF_SOC, DEVFN_TIME, DEV_TIMER, DEV_TIMER_APIC), + .init = apic_timer_init, + .supported = apic_timer_check, + .systicks = apic_get_systicks + }; return &apic_hwt; } diff --git a/lunaix-os/hal/timer/hwtimer.c b/lunaix-os/hal/timer/hwtimer.c index 4da1568..91dca07 100644 --- a/lunaix-os/hal/timer/hwtimer.c +++ b/lunaix-os/hal/timer/hwtimer.c @@ -58,8 +58,9 @@ hwtimer_init(u32_t hertz, void* tick_callback) current_timer = hwt_ctx; - struct device* timerdev = - device_addsys(NULL, &hwt_ctx->class, hwt_ctx, hwt_ctx->name); + struct device* timerdev = device_allocsys(NULL, hwt_ctx); timerdev->ops.exec_cmd = __hwtimer_ioctl; + + device_register(timerdev, &hwt_ctx->class, hwt_ctx->name); } \ No newline at end of file diff --git a/lunaix-os/includes/hal/acpi/acpi.h b/lunaix-os/includes/hal/acpi/acpi.h index de44d3a..f362b2d 100644 --- a/lunaix-os/includes/hal/acpi/acpi.h +++ b/lunaix-os/includes/hal/acpi/acpi.h @@ -15,8 +15,8 @@ #define ACPI_RSDP_SIG_L 0x20445352 // 'RSD ' #define ACPI_RSDP_SIG_H 0x20525450 // 'PTR ' -#define ACPI_MADT_SIG 0x43495041 // 'APIC' -#define ACPI_FADT_SIG 0x50434146 // 'FACP' Notice that it is not 'FADT'. +#define ACPI_MADT_SIG 0x43495041 // 'APIC' +#define ACPI_FADT_SIG 0x50434146 // 'FACP' Notice that it is not 'FADT'. // 'MCFG' (Not part of ACPI standard. See PCI Firmware Spec.) #define ACPI_MCFG_SIG 0x4746434d diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h index 186c677..3131aba 100644 --- a/lunaix-os/includes/hal/pci.h +++ b/lunaix-os/includes/hal/pci.h @@ -16,19 +16,19 @@ #define PCI_REG_STATUS_CMD 0x4 #define PCI_REG_BAR(num) (0x10 + (num - 1) * 4) -#define PCI_DEV_VENDOR(x) ((x)&0xffff) -#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_VENDOR(x) ((x) & 0xffff) +#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) -#define PCI_DEV_REV(x) (((x)&0xff)) +#define PCI_DEV_REV(x) (((x) & 0xff)) #define PCI_BUS_NUM(x) (((x) >> 16) & 0xff) #define PCI_SLOT_NUM(x) (((x) >> 11) & 0x1f) #define PCI_FUNCT_NUM(x) (((x) >> 8) & 0x7) -#define PCI_BAR_MMIO(x) (!((x)&0x1)) -#define PCI_BAR_CACHEABLE(x) ((x)&0x8) -#define PCI_BAR_TYPE(x) ((x)&0x6) +#define PCI_BAR_MMIO(x) (!((x) & 0x1)) +#define PCI_BAR_CACHEABLE(x) ((x) & 0x8) +#define PCI_BAR_TYPE(x) ((x) & 0x6) #define PCI_BAR_ADDR_MM(x) ((x) & ~0xf) #define PCI_BAR_ADDR_IO(x) ((x) & ~0x3) @@ -47,8 +47,8 @@ #define PCI_RCMD_IO_ACCESS 1 #define PCI_ADDRESS(bus, dev, funct) \ - (((bus)&0xff) << 16) | (((dev)&0xff) << 11) | (((funct)&0xff) << 8) | \ - 0x80000000 + (((bus) & 0xff) << 16) | (((dev) & 0xff) << 11) | \ + (((funct) & 0xff) << 8) | 0x80000000 #define PCI_ID_ANY (-1) @@ -79,14 +79,18 @@ struct pci_device u16_t intr_info; struct pci_base_addr bar[6]; }; +#define PCI_DEVICE(devbase) (container_of((devbase), struct pci_device, dev)) typedef void* (*pci_drv_init)(struct pci_device*); +#define PCI_DEVIDENT(vendor, id) \ + ((((id) & 0xffff) << 16) | (((vendor) & 0xffff))) + struct pci_device_def { u32_t dev_class; - u32_t dev_vendor; - u32_t dev_id; + u32_t dev_ident; + u32_t ident_mask; struct device_def devdef; }; diff --git a/lunaix-os/includes/hal/serial.h b/lunaix-os/includes/hal/serial.h index 8346fd0..1211ed0 100644 --- a/lunaix-os/includes/hal/serial.h +++ b/lunaix-os/includes/hal/serial.h @@ -24,7 +24,6 @@ struct serial_dev { struct llist_header sdev_list; struct device* dev; - mutex_t lock; struct waitq wq_rxdone; struct waitq wq_txdone; void* backend; diff --git a/lunaix-os/includes/hal/term.h b/lunaix-os/includes/hal/term.h new file mode 100644 index 0000000..79f8f67 --- /dev/null +++ b/lunaix-os/includes/hal/term.h @@ -0,0 +1,74 @@ +#ifndef __LUNAIX_TERM_H +#define __LUNAIX_TERM_H + +#include + +struct term; + +struct term_lcntl +{ + struct llist_header lcntls; + size_t (*apply)(struct term* termdev, char* line, size_t len); +}; + +struct linebuffer +{ + char* current; + char* next; + size_t sz_hlf; + off_t ptr; +}; + +struct term +{ + struct device* dev; + struct device* chdev; + struct llist_header lcntl_stack; + struct linebuffer line; + pid_t fggrp; +}; + +struct term* +term_create(); + +int +term_bind(struct term* tdev, struct device* chdev); + +int +term_push_lcntl(struct term* tdev, struct term_lcntl* lcntl); + +int +term_pop_lcntl(struct term* tdev); + +struct term_lcntl* +term_get_lcntl(u32_t lcntl_index); + +void +line_flip(struct linebuffer* lbf); + +void +line_alloc(struct linebuffer* lbf, size_t sz_hlf); + +void +line_free(struct linebuffer* lbf, size_t sz_hlf); + +static inline int +line_put_next(struct linebuffer* lbf, char val, int delta) +{ + size_t dptr = (size_t)(lbf->ptr + delta); + if (dptr >= lbf->sz_hlf) { + return 0; + } + + lbf->next[dptr] = val; + lbf->ptr++; + return 1; +} + +int +term_sendline(struct term* tdev, size_t len); + +int +term_readline(struct term* tdev, size_t len); + +#endif /* __LUNAIX_TERM_H */ diff --git a/lunaix-os/includes/lunaix/compiler.h b/lunaix-os/includes/lunaix/compiler.h index a97c8c5..72bffb7 100644 --- a/lunaix-os/includes/lunaix/compiler.h +++ b/lunaix-os/includes/lunaix/compiler.h @@ -5,5 +5,6 @@ #define unlikely(x) __builtin_expect((x), 0) #define weak_alias(name) __attribute__((weak, alias(name))) +#define weak __attribute__((weak)) #define noret __attribute__((noreturn)) #endif /* __LUNAIX_COMPILER_H */ diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index af21cb3..2d9f82b 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -8,9 +8,11 @@ #include #include #include -#include +#include #include +#include + /** * @brief Export a device definition * @@ -20,6 +22,7 @@ export_ldga_el_sfx(devdefs, id##_ldorder, ptr_t, devdef, load_order); #define load_on_demand ld_ondemand +#define load_pci_probe ld_ondemand /** * @brief Mark the device definition should be loaded automatically as earlier @@ -49,10 +52,16 @@ * @brief Declare a device class * */ -#define DEVCLASS(devif, devfn, devkind, devvar) \ +#define DEVCLASS(devif, devfn, dev) \ + (struct devclass) \ + { \ + .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), .variant = 0 \ + } + +#define DEVCLASSV(devif, devfn, dev, devvar) \ (struct devclass) \ { \ - .meta = DEV_META(devif, devfn), .device = (devkind), \ + .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), \ .variant = (devvar) \ } @@ -65,24 +74,19 @@ #define DEV_IFCAT 0x2 // a device category (as device groupping) #define DEV_IFSYS 0x3 // a system device -struct devclass -{ - u32_t meta; - u32_t device; - u32_t variant; - u32_t hash; -}; - struct device { u32_t magic; struct llist_header siblings; struct llist_header children; struct device* parent; + mutex_t lock; + // TODO investigate event polling struct hstr name; - struct devclass* class; + struct devident ident; + u32_t dev_uid; int dev_type; char name_val[DEVICE_NAME_SIZE]; @@ -115,12 +119,6 @@ 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; -} - static inline u32_t device_id_from_class(struct devclass* class) { @@ -128,53 +126,43 @@ device_id_from_class(struct devclass* class) } void -device_register_all(); +device_scan_drivers(); void -device_prepare(struct device* dev, struct devclass* class); +device_setname_vargs(struct device* dev, char* fmt, va_list args); void device_setname(struct device* dev, char* fmt, ...); void -device_setname(struct device* dev, char* fmt, ...); +device_register(struct device* dev, struct devclass* class, char* fmt, ...); -struct device* -device_add_vargs(struct device* parent, - void* underlay, - char* name_fmt, - u32_t type, - struct devclass* class, - va_list args); +void +device_create(struct device* dev, + struct device* parent, + u32_t type, + void* underlay); struct device* -device_add(struct device* parent, - struct devclass* class, - void* underlay, - u32_t type, - char* name_fmt, - ...); +device_alloc(struct device* parent, u32_t type, void* underlay); -struct device* -device_addsys(struct device* parent, - struct devclass* class, - void* underlay, - char* name_fmt, - ...); +static inline struct device* +device_allocsys(struct device* parent, void* underlay) +{ + return device_alloc(parent, DEV_IFSYS, underlay); +} -struct device* -device_addseq(struct device* parent, - struct devclass* class, - void* underlay, - char* name_fmt, - ...); +static inline struct device* +device_allocseq(struct device* parent, void* underlay) +{ + return device_alloc(parent, DEV_IFSEQ, underlay); +} -struct device* -device_addvol(struct device* parent, - struct devclass* class, - void* underlay, - char* name_fmt, - ...); +static inline struct device* +device_allocvol(struct device* parent, void* underlay) +{ + return device_alloc(parent, DEV_IFVOL, underlay); +} struct device* device_addcat(struct device* parent, char* name_fmt, ...); @@ -195,19 +183,19 @@ 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); +device_cast(void* obj); struct hbucket* device_definitions_byif(int if_type); struct device_def* -devdef_byclass(struct devclass* class); +devdef_byident(struct devident* class); + +void +device_populate_info(struct device* dev, struct dev_info* devinfo); void -device_register_all(); +device_scan_drivers(); /*------ Load hooks ------*/ @@ -220,4 +208,22 @@ device_poststage(); void device_timerstage(); +static inline void +device_lock(struct device* dev) +{ + mutex_lock(&dev->lock); +} + +static inline void +device_unlock(struct device* dev) +{ + mutex_unlock(&dev->lock); +} + +static inline int +device_locked(struct device* dev) +{ + return mutex_on_hold(&dev->lock); +} + #endif /* __LUNAIX_DEVICE_H */ diff --git a/lunaix-os/includes/lunaix/device_num.h b/lunaix-os/includes/lunaix/device_num.h index d6052cd..ad2d8a7 100644 --- a/lunaix-os/includes/lunaix/device_num.h +++ b/lunaix-os/includes/lunaix/device_num.h @@ -1,6 +1,8 @@ #ifndef __LUNAIX_DEVICE_NUM_H #define __LUNAIX_DEVICE_NUM_H +#include + /* Device metadata field (device_def::meta) @@ -49,9 +51,15 @@ 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 DEV_FNGRP(if_, function) \ + (((if_) & 0xffff) << 16) | ((function) & 0xffff) +#define DEV_UNIQUE(devkind, variant) \ + (((devkind) & 0xffff) << 16) | ((variant) & 0xffff) +#define DEV_KIND_FROM(unique) ((unique) >> 16) +#define DEV_VAR_FROM(unique) ((unique) & 0xffff) + +#define DEV_IF(fngrp) ((fngrp) >> 16) +#define DEV_FN(fngrp) (((fngrp) & 0xffff)) #define DEVIF_NON 0x0 #define DEVIF_SOC 0x1 @@ -67,15 +75,41 @@ #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 0x6 -#define DEV_SERIAL 0x7 -#define DEV_TIMER 0x8 +#define DEVFN_DISP 0x9 + +#define DEV_BUILTIN 0 +#define DEV_BUILTIN_NULL 0 +#define DEV_BUILTIN_ZERO 1 + +#define DEV_VTERM 1 +#define DEV_RNG 2 +#define DEV_RTC 3 +#define DEV_SATA 4 +#define DEV_NVME 5 +#define DEV_PCI 6 +#define DEV_UART16550 7 + +#define DEV_TIMER 8 +#define DEV_TIMER_APIC 0 +#define DEV_TIMER_HEPT 1 + +#define DEV_NULL 9 +#define DEV_ZERO 10 +#define DEV_KBD 11 +#define DEV_VGA 12 + +struct devident +{ + u32_t fn_grp; + u32_t unique; +}; + +struct devclass +{ + u32_t fn_grp; + u32_t device; + u32_t variant; + u32_t hash; +}; #endif /* __LUNAIX_DEVICE_NUM_H */ diff --git a/lunaix-os/includes/usr/lunaix/device.h b/lunaix-os/includes/usr/lunaix/device.h index 3045113..9f8d2e0 100644 --- a/lunaix-os/includes/usr/lunaix/device.h +++ b/lunaix-os/includes/usr/lunaix/device.h @@ -9,9 +9,8 @@ struct dev_info struct { - unsigned int meta; - unsigned int device; - unsigned int variant; + unsigned int group; + unsigned int unique; } dev_id; struct diff --git a/lunaix-os/includes/usr/lunaix/ioctl_defs.h b/lunaix-os/includes/usr/lunaix/ioctl_defs.h index dd5709f..d99e767 100644 --- a/lunaix-os/includes/usr/lunaix/ioctl_defs.h +++ b/lunaix-os/includes/usr/lunaix/ioctl_defs.h @@ -13,6 +13,10 @@ #define TIOCSPGRP IOREQ(1, 1) #define TIOCCLSBUF IOREQ(2, 0) #define TIOCFLUSH IOREQ(3, 0) +#define TIOCPUSH IOREQ(4, 1) +#define TIOCPOP IOREQ(5, 0) +#define TIOCSCDEV IOREQ(6, 1) +#define TIOCGCDEV IOREQ(7, 0) #define RTCIO_IUNMSK IOREQ(1, 0) #define RTCIO_IMSK IOREQ(2, 0) diff --git a/lunaix-os/includes/usr/lunaix/types.h b/lunaix-os/includes/usr/lunaix/types.h index 9650b47..1c98912 100644 --- a/lunaix-os/includes/usr/lunaix/types.h +++ b/lunaix-os/includes/usr/lunaix/types.h @@ -33,8 +33,8 @@ typedef unsigned int ino_t; typedef struct dev_t { unsigned int meta; - unsigned int devident; - unsigned int dev_uid; + unsigned int unique; + unsigned int index; } dev_t; #endif /* __LUNAIX_TYPES_H */ diff --git a/lunaix-os/kernel/block/block.c b/lunaix-os/kernel/block/block.c index 76ef778..c78cd26 100644 --- a/lunaix-os/kernel/block/block.c +++ b/lunaix-os/kernel/block/block.c @@ -318,16 +318,19 @@ __block_register(struct block_dev* bdev) return 0; } - struct device* dev = - device_addvol(blk_parent_dev, bdev->class, bdev, "sd%c", 'a' + free_slot); + struct device* dev = device_allocvol(blk_parent_dev, bdev); dev->ops.write = __block_write; dev->ops.write_page = __block_write_page; dev->ops.read = __block_read; dev->ops.read_page = __block_read_page; bdev->dev = dev; - strcpy(bdev->bdev_id, dev->name_val); + + device_register(dev, bdev->class, "sd%c", 'a' + free_slot); dev_registry[free_slot++] = bdev; + + strcpy(bdev->bdev_id, dev->name_val); + return 1; } @@ -341,8 +344,7 @@ blk_mount_part(struct block_dev* bdev, struct block_dev* pbdev = cake_grab(lbd_pile); memcpy(pbdev, bdev, sizeof(*bdev)); - struct device* dev = device_addvol( - NULL, pbdev->class, pbdev, "%sp%d", bdev->bdev_id, index + 1); + struct device* dev = device_allocvol(NULL, pbdev); dev->ops.write = __block_write; dev->ops.write_page = __block_write_page; dev->ops.read = __block_read; @@ -359,5 +361,7 @@ blk_mount_part(struct block_dev* bdev, llist_append(&bdev->parts, &pbdev->parts); + device_register(dev, pbdev->class, "%sp%d", bdev->bdev_id, index + 1); + return pbdev; } \ No newline at end of file diff --git a/lunaix-os/kernel/device/devdb.c b/lunaix-os/kernel/device/devdb.c index f77afec..1c9ee4c 100644 --- a/lunaix-os/kernel/device/devdb.c +++ b/lunaix-os/kernel/device/devdb.c @@ -2,6 +2,8 @@ #include #include +#include + #include static DECLARE_HASHTABLE(dev_registry, 32); @@ -10,8 +12,14 @@ static DEFINE_LLIST(dev_registry_flat); static struct device* adhoc_devcat; +static inline u32_t +hash_dev(u32_t fngrp, u32_t dev) +{ + return (hash_32(fngrp, 16) << 16) | (hash_32(dev, 16)); +} + void -device_register_all() +device_scan_drivers() { adhoc_devcat = device_addcat(NULL, "adhoc"); @@ -22,16 +30,16 @@ device_register_all() struct device_def* devdef; ldga_foreach(devdefs, struct device_def*, idx, devdef) { - u32_t hash = devclass_hash(devdef->class); - devdef->class.hash = hash; + struct devclass* devc = &devdef->class; + u32_t hash = hash_dev(devc->fn_grp, devc->device); + devc->hash = hash; if (!devdef->name) { devdef->name = ""; } hashtable_hash_in(dev_registry, &devdef->hlist, hash); - hashtable_hash_in( - dev_byif, &devdef->hlist_if, DEV_IF(devdef->class.meta)); + hashtable_hash_in(dev_byif, &devdef->hlist_if, DEV_IF(devc->fn_grp)); llist_append(&dev_registry_flat, &devdef->dev_list); } @@ -40,14 +48,13 @@ device_register_all() static int devclass_eq(struct devclass* c1, struct devclass* c2) { - return c1->meta == c2->meta && c1->variant == c2->variant && - c1->device == c2->device; + return c1->fn_grp == c2->fn_grp && c1->device == c2->device; } struct device_def* -devdef_byclass(struct devclass* class) +devdef_byclass(struct devclass* devc) { - u32_t hash = devclass_hash(*class); + u32_t hash = hash_dev(devc->fn_grp, devc->device); int errno; struct device_def *pos, *n; @@ -56,7 +63,7 @@ devdef_byclass(struct devclass* class) if (pos->class.hash != hash) { continue; } - if (devclass_eq(class, &pos->class)) { + if (devclass_eq(devc, &pos->class)) { break; } } @@ -64,45 +71,12 @@ devdef_byclass(struct devclass* class) return pos; } -struct device* -device_create_byclass(struct devclass* class, - u32_t type, - char* name, - int* err_code) +struct device_def* +devdef_byident(struct devident* ident) { - 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, class, 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_uid); - - return dev; + struct devclass derived = { .device = DEV_KIND_FROM(ident->unique), + .fn_grp = ident->fn_grp }; + return devdef_byclass(&derived); } struct hbucket* @@ -157,14 +131,13 @@ __devdb_twifs_lsdb(struct twimap* mapping) char flags[64]; struct device_def* def = twimap_index(mapping, struct device_def*); - int meta = def->class.meta; + int meta = def->class.fn_grp; ksnprintf(flags, 64, "if=%x,fn=%x", DEV_IF(meta), DEV_FN(meta)); twimap_printf(mapping, - "%xh:%d:%d \"%s\" %s\n", - def->class.meta, + "%xh:%d \"%s\" %s\n", + def->class.fn_grp, def->class.device, - def->class.variant, def->name, flags); } diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index d26808a..b25a9c2 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -8,8 +8,6 @@ #include #include -#include - #include #include @@ -20,16 +18,6 @@ static volatile u32_t devid = 0; struct devclass default_devclass = {}; void -device_prepare(struct device* dev, struct devclass* class) -{ - dev->magic = DEV_STRUCT_MAGIC; - dev->dev_uid = devid++; - dev->class = class ? class : &default_devclass; - - llist_init_head(&dev->children); -} - -static void device_setname_vargs(struct device* dev, char* fmt, va_list args) { size_t strlen = @@ -41,28 +29,24 @@ device_setname_vargs(struct device* dev, char* fmt, va_list args) } void -device_setname(struct device* dev, char* fmt, ...) +device_register(struct device* dev, struct devclass* class, char* fmt, ...) { va_list args; va_start(args, fmt); - device_setname_vargs(dev, fmt, args); - - va_end(args); -} + if (fmt) { + device_setname_vargs(dev, fmt, args); + } -struct device* -device_add_vargs(struct device* parent, - void* underlay, - char* name_fmt, - u32_t type, - struct devclass* class, - va_list args) -{ - struct device* dev = vzalloc(sizeof(struct device)); + if (class) { + dev->ident = (struct devident){ .fn_grp = class->fn_grp, + .unique = DEV_UNIQUE(class->device, + class->variant) }; + } - device_prepare(dev, class); + dev->dev_uid = devid++; + struct device* parent = dev->parent; if (parent) { assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT); llist_append(&parent->children, &dev->siblings); @@ -70,84 +54,47 @@ device_add_vargs(struct device* parent, llist_append(&root_list, &dev->siblings); } - if (name_fmt) { - device_setname_vargs(dev, name_fmt, args); - } - - dev->parent = parent; - dev->underlay = underlay; - dev->dev_type = type; - - return dev; -} - -struct device* -device_add(struct device* parent, - struct devclass* class, - 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, class, args); - va_end(args); - return dev; } -struct device* -device_addsys(struct device* parent, - struct devclass* class, - void* underlay, - char* name_fmt, - ...) +void +device_create(struct device* dev, + struct device* parent, + u32_t type, + void* underlay) { - va_list args; - va_start(args, name_fmt); - - struct device* dev = - device_add_vargs(parent, underlay, name_fmt, DEV_IFSYS, class, args); + dev->magic = DEV_STRUCT_MAGIC; + dev->underlay = underlay; + dev->dev_type = type; + dev->parent = parent; - va_end(args); - return dev; + llist_init_head(&dev->children); + mutex_init(&dev->lock); } struct device* -device_addseq(struct device* parent, - struct devclass* class, - void* underlay, - char* name_fmt, - ...) +device_alloc(struct device* parent, u32_t type, void* underlay) { - va_list args; - va_start(args, name_fmt); + struct device* dev = vzalloc(sizeof(struct device)); - struct device* dev = - device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, class, args); + if (!dev) { + return NULL; + } + + device_create(dev, parent, type, underlay); - va_end(args); return dev; } -struct device* -device_addvol(struct device* parent, - struct devclass* class, - void* underlay, - char* name_fmt, - ...) +void +device_setname(struct device* dev, char* fmt, ...) { va_list args; - va_start(args, name_fmt); + va_start(args, fmt); - struct device* dev = - device_add_vargs(parent, underlay, name_fmt, DEV_IFVOL, class, args); + device_setname_vargs(dev, fmt, args); va_end(args); - return dev; } struct device* @@ -156,8 +103,10 @@ device_addcat(struct device* parent, char* name_fmt, ...) va_list args; va_start(args, name_fmt); - struct device* dev = - device_add_vargs(parent, NULL, name_fmt, DEV_IFCAT, NULL, args); + struct device* dev = device_alloc(parent, DEV_IFCAT, NULL); + + device_setname_vargs(dev, name_fmt, args); + device_register(dev, NULL, NULL); va_end(args); return dev; @@ -224,24 +173,34 @@ device_getbyoffset(struct device* root_dev, int offset) return NULL; } -static inline void +void device_populate_info(struct device* dev, struct dev_info* devinfo) { - devinfo->dev_id.meta = dev->class->meta; - devinfo->dev_id.device = dev->class->device; - devinfo->dev_id.variant = dev->class->variant; + devinfo->dev_id.group = dev->ident.fn_grp; + devinfo->dev_id.unique = dev->ident.unique; if (!devinfo->dev_name.buf) { return; } - struct device_def* def = devdef_byclass(dev->class); + struct device_def* def = devdef_byident(&dev->ident); size_t buflen = devinfo->dev_name.buf_len; strncpy(devinfo->dev_name.buf, def->name, buflen); devinfo->dev_name.buf[buflen - 1] = 0; } +struct device* +device_cast(void* obj) +{ + struct device* dev = (struct device*)obj; + if (dev && dev->magic == DEV_STRUCT_MAGIC) { + return dev; + } + + return NULL; +} + __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) { int errno = -1; diff --git a/lunaix-os/kernel/device/input.c b/lunaix-os/kernel/device/input.c index 252993f..3d974a7 100644 --- a/lunaix-os/kernel/device/input.c +++ b/lunaix-os/kernel/device/input.c @@ -80,8 +80,10 @@ input_add_device(struct devclass* class, char* name_fmt, ...) va_list args; va_start(args, name_fmt); - struct device* dev = - device_add_vargs(input_devcat, idev, name_fmt, DEV_IFSEQ, class, args); + struct device* dev = device_allocseq(input_devcat, idev); + + device_setname_vargs(dev, name_fmt, args); + device_register(dev, class, NULL); idev->dev_if = dev; dev->ops.read = __input_dev_read; diff --git a/lunaix-os/kernel/fs/pcache.c b/lunaix-os/kernel/fs/pcache.c index f1969bd..8283fd1 100644 --- a/lunaix-os/kernel/fs/pcache.c +++ b/lunaix-os/kernel/fs/pcache.c @@ -133,23 +133,32 @@ pcache_write(struct v_inode* inode, void* data, u32_t len, u32_t fpos) struct pcache* pcache = inode->pg_cache; struct pcache_pg* pg; - while (buf_off < len) { + while (buf_off < len && errno >= 0) { u32_t wr_bytes = MIN(PG_SIZE - pg_off, len - buf_off); - pcache_get_page(pcache, fpos, &pg_off, &pg); + 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); - if (!pg) { - errno = inode->default_fops->write(inode, data, wr_bytes, fpos); if (errno < 0) { break; } - } else { - memcpy(pg->pg + pg_off, (data + buf_off), wr_bytes); - pcache_set_dirty(pcache, pg); - - pg->len = pg_off + wr_bytes; + if (errno < PG_SIZE) { + // EOF + len = MIN(len, buf_off + errno); + } + } else if (!pg) { + errno = inode->default_fops->write(inode, data, wr_bytes, fpos); + continue; } + memcpy(pg->pg + pg_off, (data + buf_off), wr_bytes); + pcache_set_dirty(pcache, pg); + + pg->len = pg_off + wr_bytes; buf_off += wr_bytes; fpos += wr_bytes; } diff --git a/lunaix-os/kernel/fs/probe_boot.c b/lunaix-os/kernel/fs/probe_boot.c index a935fc4..2ddc9b1 100644 --- a/lunaix-os/kernel/fs/probe_boot.c +++ b/lunaix-os/kernel/fs/probe_boot.c @@ -23,10 +23,9 @@ probe_boot_medium() int errno = pos->ops.read(pos, (void*)volp, ISO9660_READ_OFF, ISO9660_BLKSZ); if (errno < 0) { - kprintf(KINFO "failed %x:%d:%d, /dev/%s\n", - pos->class->meta, - pos->class->device, - pos->class->variant, + kprintf(KINFO "failed %xh:%xh, /dev/%s\n", + pos->ident.fn_grp, + pos->ident.unique, pos->name.value); pos = NULL; goto done; @@ -37,10 +36,9 @@ probe_boot_medium() } if (*(u32_t*)volp->sys_id == LUNAIX_ID) { - kprintf(KINFO "%x:%d:%d, /dev/%s, %s\n", - pos->class->meta, - pos->class->device, - pos->class->variant, + kprintf(KINFO "%xh:%xh, /dev/%s, %s\n", + pos->ident.fn_grp, + pos->ident.unique, pos->name.value, (char*)volp->vol_id); break; diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index cf376d2..fbb0f9f 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -1468,16 +1468,15 @@ __DEFINE_LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat) goto done; } - stat->st_rdev = (dev_t){ .meta = rdev->class->meta, - .devident = device_id_from_class(rdev->class), - .dev_uid = rdev->dev_uid }; + stat->st_rdev = (dev_t){ .meta = rdev->ident.fn_grp, + .unique = rdev->ident.unique, + .index = rdev->dev_uid }; } if (fdev) { - u32_t devident = device_id_from_class(fdev->class); - stat->st_dev = (dev_t){ .meta = fdev->class->meta, - .devident = devident, - .dev_uid = fdev->dev_uid }; + stat->st_dev = (dev_t){ .meta = fdev->ident.fn_grp, + .unique = fdev->ident.unique, + .index = fdev->dev_uid }; } done: diff --git a/lunaix-os/kernel/kinit.c b/lunaix-os/kernel/kinit.c index f5944b5..cb31ca1 100644 --- a/lunaix-os/kernel/kinit.c +++ b/lunaix-os/kernel/kinit.c @@ -52,7 +52,7 @@ kernel_bootstrap(struct boot_handoff* bhctx) /* Prepare stack trace environment */ trace_modksyms_init(bhctx); - device_register_all(); + device_scan_drivers(); // crt tty_init(ioremap(0xB8000, PG_SIZE)); diff --git a/lunaix-os/kernel/kprintf.c b/lunaix-os/kernel/kprintf.c index 15c8c14..451abe0 100644 --- a/lunaix-os/kernel/kprintf.c +++ b/lunaix-os/kernel/kprintf.c @@ -11,7 +11,7 @@ static char* log_prefix[] = { "- ", "W ", "E ", "D " }; static char* color_code[] = { "", "\033[6;0m", "\033[12;0m", "\033[9;0m" }; -void +void __kprintf_internal(const char* component, int log_level, const char* prefix, diff --git a/lunaix-os/kernel/mm/cow.c b/lunaix-os/kernel/mm/cow.c deleted file mode 100644 index a12d6e9..0000000 --- a/lunaix-os/kernel/mm/cow.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -#include - -ptr_t -vmm_dup_page(pid_t pid, ptr_t pa) -{ - ptr_t new_ppg = pmm_alloc_page(pid, 0); - vmm_set_mapping(VMS_SELF, PG_MOUNT_3, new_ppg, PG_PREM_RW, VMAP_NULL); - vmm_set_mapping(VMS_SELF, PG_MOUNT_4, pa, PG_PREM_RW, VMAP_NULL); - - asm volatile("movl %1, %%edi\n" - "movl %2, %%esi\n" - "rep movsl\n" ::"c"(1024), - "r"(PG_MOUNT_3), - "r"(PG_MOUNT_4) - : "memory", "%edi", "%esi"); - - vmm_del_mapping(VMS_SELF, PG_MOUNT_3); - vmm_del_mapping(VMS_SELF, PG_MOUNT_4); - - return new_ppg; -} \ No newline at end of file diff --git a/lunaix-os/kernel/mm/vmm.c b/lunaix-os/kernel/mm/vmm.c index 4cfb1a6..e21328f 100644 --- a/lunaix-os/kernel/mm/vmm.c +++ b/lunaix-os/kernel/mm/vmm.c @@ -3,7 +3,9 @@ #include #include #include + #include +#include LOG_MODULE("VMM") @@ -199,4 +201,24 @@ vmm_unmount_pd(ptr_t mnt) l1pt->entry[(mnt >> 22)] = 0; cpu_flush_page(mnt); return mnt; +} + +ptr_t +vmm_dup_page(pid_t pid, ptr_t pa) +{ + ptr_t new_ppg = pmm_alloc_page(pid, 0); + vmm_set_mapping(VMS_SELF, PG_MOUNT_3, new_ppg, PG_PREM_RW, VMAP_NULL); + vmm_set_mapping(VMS_SELF, PG_MOUNT_4, pa, PG_PREM_RW, VMAP_NULL); + + asm volatile("movl %1, %%edi\n" + "movl %2, %%esi\n" + "rep movsl\n" ::"c"(1024), + "r"(PG_MOUNT_3), + "r"(PG_MOUNT_4) + : "memory", "%edi", "%esi"); + + vmm_del_mapping(VMS_SELF, PG_MOUNT_3); + vmm_del_mapping(VMS_SELF, PG_MOUNT_4); + + return new_ppg; } \ No newline at end of file diff --git a/lunaix-os/kernel/process/taskfs.c b/lunaix-os/kernel/process/taskfs.c index 36ed5ee..e11068f 100644 --- a/lunaix-os/kernel/process/taskfs.c +++ b/lunaix-os/kernel/process/taskfs.c @@ -129,7 +129,7 @@ taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) return ENOENT; } - return taskfs_mknod(dnode, pid, 0, F_FILE); + return taskfs_mknod(dnode, pid, 0, F_DIR); } static struct v_file_ops taskfs_file_ops = { .close = default_file_close, diff --git a/lunaix-os/kernel/tty/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c index 17dddfd..5c18cbc 100644 --- a/lunaix-os/kernel/tty/lxconsole.c +++ b/lunaix-os/kernel/tty/lxconsole.c @@ -343,8 +343,7 @@ console_start_flushing() static int lxconsole_spawn_ttydev(struct device_def* devdef) { - struct device* tty_dev = - device_addseq(NULL, &devdef->class, &lx_console, "tty"); + struct device* tty_dev = device_allocseq(NULL, &lx_console); tty_dev->ops.write = __tty_write; tty_dev->ops.write_page = __tty_write_pg; tty_dev->ops.read = __tty_read; @@ -354,12 +353,14 @@ lxconsole_spawn_ttydev(struct device_def* devdef) waitq_init(&lx_reader); input_add_listener(__lxconsole_listener); + device_register(tty_dev, &devdef->class, "tty"); + return 0; } static struct device_def lxconsole_def = { .name = "Lunaix Virtual Console", - .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN, 0), + .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 diff --git a/lunaix-os/makefile b/lunaix-os/makefile index af90c06..af07f60 100644 --- a/lunaix-os/makefile +++ b/lunaix-os/makefile @@ -91,8 +91,7 @@ debug-qemu: all-debug @i686-elf-objcopy --only-keep-debug $(kbin) $(kbuild_dir)/kernel.dbg @qemu-system-i386 $(call get_qemu_options,$(kimg)) @sleep 1 - @$(QEMU_MON_TERM) -- telnet 127.0.0.1 $(QEMU_MON_PORT) - @gdb -s $(kbuild_dir)/kernel.dbg -ex "target remote localhost:1234" + @QMPORT=$(QEMU_MON_PORT) gdb -s $(kbuild_dir)/kernel.dbg -ex "target remote localhost:1234" debug-qemu-vscode: all-debug @i686-elf-objcopy --only-keep-debug $(kbin) $(kbuild_dir)/kernel.dbg diff --git a/lunaix-os/makeinc/qemu.mkinc b/lunaix-os/makeinc/qemu.mkinc index 12d21b8..eccf605 100644 --- a/lunaix-os/makeinc/qemu.mkinc +++ b/lunaix-os/makeinc/qemu.mkinc @@ -8,6 +8,8 @@ get_qemu_options = -s -S -m 1G \ -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 \ -drive id=cdrom,file="$(1)",readonly=on,if=none,format=raw \ diff --git a/lunaix-os/usr/init/init.c b/lunaix-os/usr/init/init.c index b3eaae5..7f7ca5e 100644 --- a/lunaix-os/usr/init/init.c +++ b/lunaix-os/usr/init/init.c @@ -19,8 +19,6 @@ main(int argc, const char** argv) return 0; } - printf("(%p) user space!\n", (void*)main); - if ((err = symlink("/usr", "/mnt/lunaix-os/usr"))) { syslog(2, "symlink /usr:/mnt/lunaix-os/usr (%d)\n", errno); return 0; diff --git a/lunaix-os/usr/sh/sh.c b/lunaix-os/usr/sh/sh.c index 8ce8617..0a91aa7 100644 --- a/lunaix-os/usr/sh/sh.c +++ b/lunaix-os/usr/sh/sh.c @@ -175,7 +175,6 @@ sh_loop() void main() { - printf("\n Simple shell. Use or to scroll.\n\n"); sh_loop(); _exit(0); } \ No newline at end of file diff --git a/lunaix-os/usr/stat/main.c b/lunaix-os/usr/stat/main.c index 541378f..108f462 100644 --- a/lunaix-os/usr/stat/main.c +++ b/lunaix-os/usr/stat/main.c @@ -63,10 +63,7 @@ main(int argc, char* argv[]) dev = &stat.st_rdev; } - printf("Device: %xh:%d:%d;\n", - dev->meta, - dev->devident >> 16, - dev->devident & 0xffff); + printf("Device: %xh:%xh@%d;\n", dev->meta, dev->unique, dev->index); close(fd); return 0;