"-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"
}
}
/**
- * @brief Flush TLB
+ * @brief Flush a certain TLB record
*
* @return u32_t
*/
asm volatile("invlpg (%0)" ::"r"(va) : "memory");
}
+/**
+ * @brief Flush entire TLB
+ *
+ */
static inline void
cpu_flush_vmspace()
{
asm("hlt");
}
+/**
+ * @brief Read exeception address
+ *
+ * @return ptr_t
+ */
static inline ptr_t
cpu_ldeaddr()
{
#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
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
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);
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);
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);
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;
}
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;
}
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;
}
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;
done:
int rdlen = sdev->wr_len;
- mutex_unlock(&sdev->lock);
+ device_unlock(sdev->dev);
return rdlen;
}
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;
}
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;
llist_append(&serial_devs, &sdev->sdev_list);
// llist_init_head(&sdev->cmds);
+ class->variant++;
+ device_register(dev, class, "ttyS%d", class->variant);
+
return sdev;
}
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;
}
}
}
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
};
--- /dev/null
+/**
+ * @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 <lunaix/compiler.h>
+#include <lunaix/device.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#include <sys/cpu.h>
+
+#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();
+}
--- /dev/null
+#ifndef __LUNAIX_VGA_H
+#define __LUNAIX_VGA_H
+
+#include <lunaix/types.h>
+
+/* -- 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 */
--- /dev/null
+#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
--- /dev/null
+#include <lunaix/device.h>
+#include <lunaix/mm/mmio.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+#include <lunaix/status.h>
+
+#include <hal/pci.h>
+#include <sys/pci_hba.h>
+
+#include <klibc/string.h>
+
+#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
--- /dev/null
+#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
static DEFINE_LLIST(pci_devices);
+static struct device* pcidev_cat;
+
void
pci_probe_msi_info(struct pci_device* device);
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;
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);
}
llist_append(&pci_devices, &device->dev_chain);
+ device_register(&device->dev, &pos->devdef.class, "%x:%x", vendor, devid);
return device;
static int
pci_load_devices(struct device_def* def)
{
+ pcidev_cat = device_addcat(NULL, "pci");
+
pci_scan();
return 0;
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);
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
}
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;
}
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
--- /dev/null
+#include <hal/term.h>
+
+#include <lunaix/process.h>
+
+#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
--- /dev/null
+#include <hal/term.h>
+#include <klibc/string.h>
+#include <lunaix/fs.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+#include <lunaix/status.h>
+
+#include <usr/lunaix/ioctl_defs.h>
+
+#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
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;
}
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
#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
#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)
#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)
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;
};
{
struct llist_header sdev_list;
struct device* dev;
- mutex_t lock;
struct waitq wq_rxdone;
struct waitq wq_txdone;
void* backend;
--- /dev/null
+#ifndef __LUNAIX_TERM_H
+#define __LUNAIX_TERM_H
+
+#include <lunaix/device.h>
+
+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 */
#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 */
#include <lunaix/ds/hstr.h>
#include <lunaix/ds/ldga.h>
#include <lunaix/ds/llist.h>
-#include <lunaix/ds/semaphore.h>
+#include <lunaix/ds/mutex.h>
#include <lunaix/types.h>
+#include <usr/lunaix/device.h>
+
/**
* @brief Export a device definition
*
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
* @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) \
}
#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];
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)
{
}
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, ...);
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 ------*/
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 */
#ifndef __LUNAIX_DEVICE_NUM_H
#define __LUNAIX_DEVICE_NUM_H
+#include <lunaix/types.h>
+
/*
Device metadata field (device_def::meta)
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
#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 */
struct
{
- unsigned int meta;
- unsigned int device;
- unsigned int variant;
+ unsigned int group;
+ unsigned int unique;
} dev_id;
struct
#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)
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 */
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;
}
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;
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
#include <lunaix/fs/twifs.h>
#include <lunaix/status.h>
+#include <lib/hash.h>
+
#include <klibc/stdio.h>
static DECLARE_HASHTABLE(dev_registry, 32);
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");
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 = "<unspecified>";
}
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);
}
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;
if (pos->class.hash != hash) {
continue;
}
- if (devclass_eq(class, &pos->class)) {
+ if (devclass_eq(devc, &pos->class)) {
break;
}
}
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*
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);
}
#include <lunaix/syscall.h>
#include <lunaix/syscall_utils.h>
-#include <usr/lunaix/device.h>
-
#include <klibc/stdio.h>
#include <klibc/string.h>
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 =
}
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);
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*
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;
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;
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;
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;
}
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;
}
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;
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:
/* Prepare stack trace environment */
trace_modksyms_init(bhctx);
- device_register_all();
+ device_scan_drivers();
// crt
tty_init(ioremap(0xB8000, PG_SIZE));
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,
+++ /dev/null
-#include <lunaix/mm/pmm.h>
-#include <lunaix/mm/vmm.h>
-
-#include <sys/mm/mempart.h>
-
-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
#include <lunaix/mm/vmm.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
+
#include <sys/cpu.h>
+#include <sys/mm/mempart.h>
LOG_MODULE("VMM")
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
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,
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;
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
@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
-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 \
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;
void
main()
{
- printf("\n Simple shell. Use <PG_UP> or <PG_DOWN> to scroll.\n\n");
sh_loop();
_exit(0);
}
\ No newline at end of file
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;