aboutsummaryrefslogtreecommitdiff
path: root/vgasrc/vgaio.c
diff options
context:
space:
mode:
Diffstat (limited to 'vgasrc/vgaio.c')
-rw-r--r--vgasrc/vgaio.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/vgasrc/vgaio.c b/vgasrc/vgaio.c
new file mode 100644
index 0000000..88fd01e
--- /dev/null
+++ b/vgasrc/vgaio.c
@@ -0,0 +1,312 @@
+// VGA io port access
+//
+// Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2001-2008 the LGPL VGABios developers Team
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "ioport.h" // outb
+#include "bregs.h" // struct bregs
+#include "farptr.h" // SET_FARVAR
+#include "vgatables.h" // VGAREG_*
+
+
+/****************************************************************
+ * Attribute control
+ ****************************************************************/
+
+void
+biosfn_set_border_color(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(0x00, VGAREG_ACTL_ADDRESS);
+ u8 al = regs->bl & 0x0f;
+ if (al & 0x08)
+ al += 0x08;
+ outb(al, VGAREG_ACTL_WRITE_DATA);
+ u8 bl = regs->bl & 0x10;
+
+ int i;
+ for (i = 1; i < 4; i++) {
+ outb(i, VGAREG_ACTL_ADDRESS);
+
+ al = inb(VGAREG_ACTL_READ_DATA);
+ al &= 0xef;
+ al |= bl;
+ outb(al, VGAREG_ACTL_WRITE_DATA);
+ }
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_set_overscan_border_color(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(0x11, VGAREG_ACTL_ADDRESS);
+ outb(regs->bh, VGAREG_ACTL_WRITE_DATA);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_read_overscan_border_color(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(0x11, VGAREG_ACTL_ADDRESS);
+ regs->bh = inb(VGAREG_ACTL_READ_DATA);
+ inb(VGAREG_ACTL_RESET);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_set_palette(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ u8 bl = regs->bl & 0x01;
+ int i;
+ for (i = 1; i < 4; i++) {
+ outb(i, VGAREG_ACTL_ADDRESS);
+
+ u8 al = inb(VGAREG_ACTL_READ_DATA);
+ al &= 0xfe;
+ al |= bl;
+ outb(al, VGAREG_ACTL_WRITE_DATA);
+ }
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_set_single_palette_reg(u8 reg, u8 val)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(reg, VGAREG_ACTL_ADDRESS);
+ outb(val, VGAREG_ACTL_WRITE_DATA);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+u8
+biosfn_get_single_palette_reg(u8 reg)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(reg, VGAREG_ACTL_ADDRESS);
+ u8 v = inb(VGAREG_ACTL_READ_DATA);
+ inb(VGAREG_ACTL_RESET);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+ return v;
+}
+
+void
+biosfn_set_all_palette_reg(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+
+ u8 *data_far = (u8*)(regs->dx + 0);
+ int i;
+ for (i = 0; i < 0x10; i++) {
+ outb(i, VGAREG_ACTL_ADDRESS);
+ u8 val = GET_FARVAR(regs->es, *data_far);
+ outb(val, VGAREG_ACTL_WRITE_DATA);
+ data_far++;
+ }
+ outb(0x11, VGAREG_ACTL_ADDRESS);
+ outb(GET_FARVAR(regs->es, *data_far), VGAREG_ACTL_WRITE_DATA);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_get_all_palette_reg(struct bregs *regs)
+{
+ u8 *data_far = (u8*)(regs->dx + 0);
+ int i;
+ for (i = 0; i < 0x10; i++) {
+ inb(VGAREG_ACTL_RESET);
+ outb(i, VGAREG_ACTL_ADDRESS);
+ SET_FARVAR(regs->es, *data_far, inb(VGAREG_ACTL_READ_DATA));
+ data_far++;
+ }
+ inb(VGAREG_ACTL_RESET);
+ outb(0x11, VGAREG_ACTL_ADDRESS);
+ SET_FARVAR(regs->es, *data_far, inb(VGAREG_ACTL_READ_DATA));
+ inb(VGAREG_ACTL_RESET);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_toggle_intensity(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(0x10, VGAREG_ACTL_ADDRESS);
+ u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0x7f) | ((regs->bl & 0x01) << 3);
+ outb(val, VGAREG_ACTL_WRITE_DATA);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_select_video_dac_color_page(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(0x10, VGAREG_ACTL_ADDRESS);
+ u8 val = inb(VGAREG_ACTL_READ_DATA);
+ if (!(regs->bl & 0x01)) {
+ val = (val & 0x7f) | (regs->bh << 7);
+ outb(val, VGAREG_ACTL_WRITE_DATA);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+ return;
+ }
+ inb(VGAREG_ACTL_RESET);
+ outb(0x14, VGAREG_ACTL_ADDRESS);
+ u8 bh = regs->bh;
+ if (!(val & 0x80))
+ bh <<= 2;
+ bh &= 0x0f;
+ outb(bh, VGAREG_ACTL_WRITE_DATA);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+}
+
+void
+biosfn_read_video_dac_state(struct bregs *regs)
+{
+ inb(VGAREG_ACTL_RESET);
+ outb(0x10, VGAREG_ACTL_ADDRESS);
+ u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
+
+ inb(VGAREG_ACTL_RESET);
+ outb(0x14, VGAREG_ACTL_ADDRESS);
+ u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
+ if (!(val1 & 0x01))
+ val2 >>= 2;
+
+ inb(VGAREG_ACTL_RESET);
+ outb(0x20, VGAREG_ACTL_ADDRESS);
+
+ regs->bl = val1;
+ regs->bh = val2;
+}
+
+
+/****************************************************************
+ * DAC control
+ ****************************************************************/
+
+void
+biosfn_set_single_dac_reg(struct bregs *regs)
+{
+ outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
+ outb(regs->dh, VGAREG_DAC_DATA);
+ outb(regs->ch, VGAREG_DAC_DATA);
+ outb(regs->cl, VGAREG_DAC_DATA);
+}
+
+void
+biosfn_read_single_dac_reg(struct bregs *regs)
+{
+ outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
+ regs->dh = inb(VGAREG_DAC_DATA);
+ regs->ch = inb(VGAREG_DAC_DATA);
+ regs->cl = inb(VGAREG_DAC_DATA);
+}
+
+void
+biosfn_set_all_dac_reg(struct bregs *regs)
+{
+ outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
+ u8 *data_far = (u8*)(regs->dx + 0);
+ int count = regs->cx;
+ while (count) {
+ outb(GET_FARVAR(regs->es, *data_far), VGAREG_DAC_DATA);
+ data_far++;
+ outb(GET_FARVAR(regs->es, *data_far), VGAREG_DAC_DATA);
+ data_far++;
+ outb(GET_FARVAR(regs->es, *data_far), VGAREG_DAC_DATA);
+ data_far++;
+ count--;
+ }
+}
+
+void
+biosfn_read_all_dac_reg(struct bregs *regs)
+{
+ outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
+ u8 *data_far = (u8*)(regs->dx + 0);
+ int count = regs->cx;
+ while (count) {
+ SET_FARVAR(regs->es, *data_far, inb(VGAREG_DAC_DATA));
+ data_far++;
+ SET_FARVAR(regs->es, *data_far, inb(VGAREG_DAC_DATA));
+ data_far++;
+ SET_FARVAR(regs->es, *data_far, inb(VGAREG_DAC_DATA));
+ data_far++;
+ count--;
+ }
+}
+
+void
+biosfn_set_pel_mask(struct bregs *regs)
+{
+ outb(regs->bl, VGAREG_PEL_MASK);
+}
+
+void
+biosfn_read_pel_mask(struct bregs *regs)
+{
+ regs->bl = inb(VGAREG_PEL_MASK);
+}
+
+
+/****************************************************************
+ * Memory control
+ ****************************************************************/
+
+void
+biosfn_set_text_block_specifier(struct bregs *regs)
+{
+ outw((regs->bl << 8) | 0x03, VGAREG_SEQU_ADDRESS);
+}
+
+void
+get_font_access()
+{
+ outw(0x0100, VGAREG_SEQU_ADDRESS);
+ outw(0x0402, VGAREG_SEQU_ADDRESS);
+ outw(0x0704, VGAREG_SEQU_ADDRESS);
+ outw(0x0300, VGAREG_SEQU_ADDRESS);
+ outw(0x0204, VGAREG_GRDC_ADDRESS);
+ outw(0x0005, VGAREG_GRDC_ADDRESS);
+ outw(0x0406, VGAREG_GRDC_ADDRESS);
+}
+
+void
+release_font_access()
+{
+ outw(0x0100, VGAREG_SEQU_ADDRESS);
+ outw(0x0302, VGAREG_SEQU_ADDRESS);
+ outw(0x0304, VGAREG_SEQU_ADDRESS);
+ outw(0x0300, VGAREG_SEQU_ADDRESS);
+ u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
+ outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
+ outw(0x0004, VGAREG_GRDC_ADDRESS);
+ outw(0x1005, VGAREG_GRDC_ADDRESS);
+}
+
+
+/****************************************************************
+ * Misc
+ ****************************************************************/
+
+void
+biosfn_enable_video_addressing(struct bregs *regs)
+{
+ u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
+ u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
+ outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
+ regs->ax = 0x1212;
+}
+
+void
+init_vga_card()
+{
+ // switch to color mode and enable CPU access 480 lines
+ outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
+ // more than 64k 3C4/04
+ outb(0x04, VGAREG_SEQU_ADDRESS);
+ outb(0x02, VGAREG_SEQU_DATA);
+}