iso_inspect/
unused/
+.gdb_history
+
**.o
**.d
\ No newline at end of file
static struct pci_device_def ahcidef = {
.dev_class = AHCI_HBA_CLASS,
- .ident_mask = 0x0,
+ .ident_mask = PCI_MATCH_ANY,
.devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA),
.name = "Serial ATA Controller",
.init_for = ahci_driver_init }
};
-EXPORT_DEVICE(ahci, &ahcidef.devdef, load_pci_probe);
\ No newline at end of file
+EXPORT_PCI_DEVICE(ahci, &ahcidef);
\ No newline at end of file
--- /dev/null
+#include <lunaix/compiler.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+#include <lunaix/status.h>
+
+#include <hal/gfxm.h>
+
+#include <klibc/string.h>
+
+DEFINE_LLIST(gfxa_flat);
+DECLARE_HASHTABLE(gfxa_idset, 8);
+
+struct device* gfxa_devcat = NULL;
+static int id = 0;
+
+static struct devclass gfxa_class = DEVCLASS(DEV_BUILTIN, DEVFN_DISP, DEV_GFXA);
+
+static int
+__gfxa_cmd_router(struct device* dev, u32_t req, va_list args)
+{
+ struct gfxa* gfxa = (struct gfxa*)dev->underlay;
+ struct disp_profile* disp = &gfxa->disp_info;
+
+ switch (req) {
+ case GFX_ADAPTER_INFO: {
+ struct gfxa_info* info = va_arg(args, struct gfxa_info*);
+ *info =
+ (struct gfxa_info){ .disp_mode = { .w_px = disp->mon.w_px,
+ .h_px = disp->mon.h_px,
+ .freq = disp->mon.freq,
+ .depth = disp->mon.depth } };
+ gfxa->ops.hwioctl(gfxa, req, args);
+ break;
+ };
+ case GFX_ADAPTER_CHMODE: {
+ struct gfxa_mon* mon_info = va_arg(args, struct gfxa_mon*);
+ gfxa->disp_info.mon = *mon_info;
+
+ return gfxa->ops.update_profile(gfxa);
+ };
+ case GFX_ADAPTER_VMCPY:
+ case GFX_ADAPTER_LFBCPY: {
+ void* buf = va_arg(args, void*);
+ off_t off = va_arg(args, off_t);
+ size_t len = va_arg(args, size_t);
+ if (req == GFX_ADAPTER_VMCPY) {
+ return gfxa->ops.vmcpy(gfxa, buf, off, len);
+ }
+ return gfxa->ops.lfbcpy(gfxa, buf, off, len);
+ };
+ case GFX_ADAPTER_REG_WR:
+ case GFX_ADAPTER_REG_RD: {
+ u32_t* reg_addrmap = va_arg(args, u32_t*);
+ void* reg_val = va_arg(args, void*);
+ size_t reg_count = va_arg(args, size_t);
+
+ if (req == GFX_ADAPTER_LUT_RD) {
+ return gfxa->ops.rreads(gfxa, reg_addrmap, reg_val, reg_count);
+ }
+ return gfxa->ops.rwrites(gfxa, reg_addrmap, reg_val, reg_count);
+ };
+ case GFX_ADAPTER_LUT_RD: {
+ struct gfxa_clut* clut = va_arg(args, struct gfxa_clut*);
+ if (!clut->val || !clut->len) {
+ return disp->clut.len;
+ }
+
+ size_t clut_len = MIN(clut->len, disp->clut.len);
+ memcpy(clut->val, disp->clut.val, clut_len * sizeof(color_t));
+ return clut_len;
+ };
+ case GFX_ADAPTER_LUT_WR: {
+ struct gfxa_clut* clut = va_arg(args, struct gfxa_clut*);
+ int err = gfxm_set_lut(gfxa, clut->val, clut->len);
+ if (!err) {
+ err = gfxa->ops.update_profile(gfxa);
+ }
+ return err;
+ };
+ default:
+ return gfxa->ops.hwioctl(gfxa, req, args);
+ }
+
+ return 0;
+}
+
+struct gfxa*
+gfxm_alloc_adapter(void* hw_obj)
+{
+ if (unlikely(!gfxa_devcat)) {
+ gfxa_devcat = device_addcat(NULL, "gfx");
+ }
+
+ struct gfxa* gfxa = valloc(sizeof(struct gfxa));
+ struct device* gfxa_dev = device_allocsys(gfxa_devcat, gfxa);
+
+ *gfxa = (struct gfxa){ .dev = gfxa_dev, .hw_obj = hw_obj };
+
+ gfxa_dev->ops.exec_cmd = __gfxa_cmd_router;
+
+ return gfxa;
+}
+
+void
+gfxm_register(struct gfxa* gfxa)
+{
+ gfxa->id = gfxa_class.variant++;
+
+ llist_append(&gfxa_flat, &gfxa->gfxas);
+ hashtable_hash_in(gfxa_idset, &gfxa->gfxas_id, gfxa->id);
+
+ device_register(gfxa->dev, &gfxa_class, "gfxa%d", gfxa->id);
+}
+
+struct gfxa*
+gfxm_adapter(int gfxa_id)
+{
+ struct gfxa *pos, *n;
+ hashtable_hash_foreach(gfxa_idset, gfxa_id, pos, n, gfxas_id)
+ {
+ if (pos->id == gfxa_id) {
+ return pos;
+ }
+ }
+
+ return NULL;
+}
+
+int
+gfxm_set_lut(struct gfxa* gfxa, u32_t* lut, size_t len)
+{
+ // It is generally not feasible for graphic adapter with >256 colors still
+ // using color lut
+ if (unlikely(len > 256)) {
+ return EINVAL;
+ }
+
+ struct disp_profile* disp = &gfxa->disp_info;
+ size_t lutsz = len * sizeof(*lut);
+
+ if (disp->clut.len != len) {
+ vfree_safe(disp->clut.val);
+ disp->clut.val = valloc(lutsz);
+ disp->clut.len = len;
+ }
+
+ memcpy(disp->clut.val, lut, lutsz);
+
+ return 0;
+}
\ No newline at end of file
#include <lunaix/device.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
+#include <lunaix/status.h>
#include <sys/cpu.h>
// framebuffer: 16bit granule
u32_t divsor = 2 * 2;
- if (state->lut.len == 256) {
+ if (state->crt.depth == 256) {
// if 8 bit color is used, 2 pixels per granule
divsor *= 2;
} else if ((state->options & VGA_MODE_GFX)) {
}
void
-vga_update_palette(struct vga* state)
+vga_update_palette(struct vga* state, u32_t* lut, size_t len)
{
- state->reg_ops.set_dac_palette(state);
-
u32_t index[16];
- u32_t clr_len = MIN(state->lut.len, 16);
+ u32_t clr_len = MIN(len, 16);
for (size_t i = 0; i < clr_len; i++) {
index[i] = i;
}
+ state->reg_ops.set_dac_palette(state, lut, len);
state->reg_ops.set_seq(state, VGA_ARX, 0, index, clr_len);
}
-void
+int
vga_reload_config(struct vga* state)
{
cpu_disable_interrupt();
+ int err = 0;
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");
+ u32_t color = state->crt.depth;
+ if (!(color == 2 || color == 4 || color == 16 || color == 256)) {
+ err = EINVAL;
+ goto done;
+ }
- if (!(state->options & VGA_MODE_GFX)) {
- assert(color < 256);
+ if (!(state->options & VGA_MODE_GFX) && color > 256) {
+ err = EINVAL;
+ goto done;
}
// estimate actual fb size
total_px = total_px * 2;
}
- assert(state->fb_sz >= total_px);
- state->fb_sz = total_px;
+ if (state->fb_sz && state->fb_sz < total_px) {
+ err = EINVAL;
+ }
- reg->write(state, VGA_SRX, VGA_SR00, 0x0, ALL_FIELDS);
+ state->fb_sz = total_px;
// 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);
+ if (!(clk_f && clk_f <= 28)) {
+ err = EINVAL;
+ }
// require 28 MHz clock
if (clk_f > 25) {
}
// 25 MHz clock: 0b00 << 2
+ reg->write(state, VGA_SRX, VGA_SR00, 0x0, ALL_FIELDS);
reg->write(state, VGA_MISCX, 0, misc, 0b1111);
// SEQN_CLK: shift every CCLK, DCLK passthrough, 8/9 DCLK
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);
+ // Legacy GFX FB (for compatibility): 0xb8000, GFX mode
+ reg->write(state, VGA_GRX, VGA_GR06, 0b1111, ALL_FIELDS);
} else { // AN MOODE
// Only map 0,1 enabled, (ascii and attribute)
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);
+done:
cpu_enable_interrupt();
+ return err;
}
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*);
+ void (*set_dac_palette)(struct vga*, u32_t*, size_t);
};
struct vga
size_t pel_dot; // pixel per dot clock
size_t freq;
size_t fb_off;
+ size_t depth;
} crt;
- struct
- {
- u32_t* colors;
- u32_t len;
- } lut;
-
struct vga_regops reg_ops;
};
void
vga_config_rect(struct vga*, size_t width, size_t hight, size_t freq, int d9);
-void
+int
vga_reload_config(struct vga*);
+void
+vga_update_palette(struct vga* state, u32_t* lut, size_t len);
+
#endif /* __LUNAIX_VGA_H */
--- /dev/null
+#include "vga.h"
+#include <hal/gfxm.h>
+#include <klibc/string.h>
+
+static int
+__vga_gfxa_update_profile(struct gfxa* gfxa)
+{
+ struct vga* v = (struct vga*)gfxa->hw_obj;
+ struct disp_profile* profile = &gfxa->disp_info;
+
+ v->crt.depth = profile->mon.depth;
+ v->options = VGA_MODE_GFX;
+
+ vga_config_rect(
+ v, profile->mon.w_px, profile->mon.h_px, profile->mon.freq, 0);
+
+ int err = vga_reload_config(v);
+
+ if (!err && profile->clut.val) {
+ vga_update_palette(v, profile->clut.val, profile->clut.len);
+ }
+
+ return err;
+}
+
+static int
+__vga_gfxa_rreads(struct gfxa* gfxa, u32_t* map, void* rxbuf, size_t map_sz)
+{
+ return 0;
+}
+
+static int
+__vga_gfxa_rwrites(struct gfxa* gfxa, u32_t* map, void* txbuf, size_t map_sz)
+{
+ return 0;
+}
+
+static int
+__vga_gfxa_vmcpy(struct gfxa* gfxa, void* buf, off_t off, size_t sz)
+{
+ struct vga* v = (struct vga*)gfxa->hw_obj;
+
+ if (off + sz > v->fb_sz) {
+ return 0;
+ }
+
+ ptr_t vram_start = v->fb + off;
+ memcpy((void*)vram_start, buf, sz);
+
+ return sz;
+}
+
+static int
+__vga_gfxa_lfbcpy(struct gfxa* gfxa, void* buf, off_t off, size_t sz)
+{
+ return __vga_gfxa_vmcpy(gfxa, buf, off, sz);
+}
+
+static int
+__vga_gfxa_hwioctl(struct gfxa* gfxa, int req, va_list args)
+{
+ // TODO
+ return 0;
+}
+
+struct gfxa_ops vga_gfxa_ops = { .update_profile = __vga_gfxa_update_profile,
+ .rreads = __vga_gfxa_rreads,
+ .rwrites = __vga_gfxa_rwrites,
+ .vmcpy = __vga_gfxa_vmcpy,
+ .lfbcpy = __vga_gfxa_lfbcpy,
+ .hwioctl = __vga_gfxa_hwioctl };
\ No newline at end of file
}
static void
-vga_mmio_set_dacp(struct vga* v)
+vga_mmio_set_dacp(struct vga* v, u32_t* lut, size_t len)
{
#define R(c) (u8_t)(((c) & 0xff0000) >> 16)
#define G(c) (u8_t)(((c) & 0x00ff00) >> 8)
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];
+ for (size_t i = 0; i < len; i++) {
+ u32_t color = lut[i];
*reg_dat = R(color);
*reg_dat = G(color);
*reg_dat = B(color);
#include <lunaix/spike.h>
#include <lunaix/status.h>
+#include <hal/gfxm.h>
#include <hal/pci.h>
#include <sys/pci_hba.h>
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);
+ struct gfxa* vga_gfxa = gfxm_alloc_adapter(vga_state);
+ extern struct gfxa_ops vga_gfxa_ops;
+ vga_gfxa->ops = vga_gfxa_ops;
- // TEMP: Test the change of VGA display mode and resolution
- // vga_reload_config(vga_state);
+ // Preload a VESA-compilant configuration
+ vga_gfxa->disp_info = (struct disp_profile){
+ .mon = { .w_px = 640, .h_px = 480, .freq = 60, .depth = 16 }
+ };
+
+ gfxm_register(vga_gfxa);
return 0;
}
static struct pci_device_def vga_pci_devdef = {
.dev_class = VGA_PCI_CLASS,
.dev_ident = PCI_DEVIDENT(0x1234, 0x1111),
- .ident_mask = -1,
+ .ident_mask = PCI_MATCH_EXACT,
.devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_DISP, DEV_VGA),
- .name = "VGA Generic Driver",
+ .name = "Generic VGA",
.init_for = vga_pci_init }
};
-EXPORT_DEVICE(vga_pci, &vga_pci_devdef.devdef, load_pci_probe);
\ No newline at end of file
+EXPORT_PCI_DEVICE(vga_pci, &vga_pci_devdef);
\ No newline at end of file
return 1;
}
+static void
+__pci_read_binding(struct twimap* map)
+{
+ struct pci_device* pcidev = twimap_data(map, struct pci_device*);
+ // check if device binding has been initialized
+ struct device* dev = device_cast(&pcidev->dev);
+ if (!dev) {
+ return;
+ }
+
+ twimap_printf(map, "0x%x:0x%x", dev->ident.fn_grp, dev->ident.unique);
+}
+
void
pci_build_fsmapping()
{
map = twifs_mapping(pci_dev, pos, "class");
map->read = __pci_read_class;
+ map = twifs_mapping(pci_dev, pos, "binding");
+ map->read = __pci_read_binding;
+
map = twifs_mapping(pci_dev, pos, "io_bases");
map->read = __pci_bar_read;
map->go_next = __pci_bar_gonext;
--- /dev/null
+#ifndef __LUNAIX_GFXM_H
+#define __LUNAIX_GFXM_H
+
+#include <lunaix/device.h>
+#include <usr/lunaix/gfx.h>
+
+struct gfxa;
+
+struct disp_profile
+{
+ struct gfxa_mon mon;
+
+ struct
+ {
+ color_t* val;
+ size_t len;
+ } clut;
+};
+
+struct gfxa_ops
+{
+ int (*update_profile)(struct gfxa*);
+ /**
+ * @brief Read adapter registers
+ *
+ */
+ int (*rreads)(struct gfxa*, u32_t* map, void* rxbuf, size_t map_sz);
+ /**
+ * @brief Write adapter registers
+ *
+ */
+ int (*rwrites)(struct gfxa*, u32_t* map, void* txbuf, size_t map_sz);
+ /**
+ * @brief send data to VRAM
+ *
+ */
+ int (*vmcpy)(struct gfxa*, void*, off_t, size_t);
+ /**
+ * @brief send logical frame buffer to adapter
+ *
+ */
+ int (*lfbcpy)(struct gfxa*, void*, off_t, size_t);
+ /**
+ * @brief Execute hardware dependent ioctl command
+ *
+ */
+ int (*hwioctl)(struct gfxa*, int, va_list);
+};
+
+struct gfxa
+{
+ struct device* dev;
+ struct llist_header gfxas;
+ struct hlist_node gfxas_id;
+ struct disp_profile disp_info;
+ int id;
+ void* hw_obj;
+
+ struct gfxa_ops ops;
+};
+
+struct gfxa*
+gfxm_alloc_adapter(void* hw_obj);
+
+void
+gfxm_register(struct gfxa*);
+
+struct gfxa*
+gfxm_adapter(int gfxa_id);
+
+int
+gfxm_set_lut(struct gfxa*, color_t* lut, size_t len);
+
+#endif /* __LUNAIX_GFXM_H */
\ No newline at end of file
#include <lunaix/ds/llist.h>
#include <lunaix/types.h>
+#define EXPORT_PCI_DEVICE(id, pci_devdef) \
+ EXPORT_DEVICE(id, &(pci_devdef)->devdef, load_pci_probe)
+
+#define PCI_MATCH_EXACT -1
+#define PCI_MATCH_ANY 0
+#define PCI_MATCH_VENDOR 0xffff
+
#define PCI_TDEV 0x0
#define PCI_TPCIBRIDGE 0x1
#define PCI_TCARDBRIDGE 0x2
#define DEV_NULL 9
#define DEV_ZERO 10
#define DEV_KBD 11
-#define DEV_VGA 12
+#define DEV_GFXA 12
+#define DEV_VGA 13
struct devident
{
--- /dev/null
+#ifndef __LUNAIX_UGFX_H
+#define __LUNAIX_UGFX_H
+
+#define GFX_CMDA(type, cmd_id) (((type) << 8) | ((cmd_id) & 0xf))
+
+#define GFX_ADAPTER_INFO 1
+#define GFX_ADAPTER_REG_RD 2
+#define GFX_ADAPTER_REG_WR 3
+#define GFX_ADAPTER_CHMODE 4
+#define GFX_ADAPTER_LUT_WR 5
+#define GFX_ADAPTER_LUT_RD 6
+#define GFX_ADAPTER_VMCPY 7
+#define GFX_ADAPTER_LFBCPY 8
+
+typedef unsigned int color_t;
+
+struct gfxa_info
+{
+ struct
+ {
+ unsigned int w_px;
+ unsigned int h_px;
+ unsigned int depth;
+ unsigned int freq;
+ } disp_mode;
+
+ void* hwdep_info;
+};
+
+struct gfxa_mon
+{
+ unsigned int w_px;
+ unsigned int h_px;
+ unsigned int depth;
+ unsigned int freq;
+};
+
+struct gfxa_clut
+{
+ color_t* val;
+ size_t len;
+};
+
+#endif /* __LUNAIX_UGFX_H */