Mirroring from commit 106549a4362f6b499da522f8f8f5ed9f98388f87 from Coreboot upstream

This commit is contained in:
2026-02-17 08:55:05 +10:00
commit 5e919b3ee7
279 changed files with 89283 additions and 0 deletions
+222
View File
@@ -0,0 +1,222 @@
# Kconfig SeaBIOS VGA BIOS configuration
menu "VGA ROM"
choice
prompt "VGA Hardware Type"
default NO_VGABIOS
config NO_VGABIOS
bool "None"
help
Do not build a VGA BIOS.
config VGA_STANDARD_VGA
depends on QEMU
bool "QEMU/Bochs Original IBM 256K VGA"
select VGA_STDVGA_PORTS
help
Build basic VGA BIOS support (pre Super-VGA) for use
on emulators.
config VGA_CIRRUS
depends on QEMU
bool "QEMU/Bochs Cirrus SVGA"
select VGA_STDVGA_PORTS
help
Build support for Cirrus VGA emulation found on QEMU
and Bochs emulators. This is for emulators; it is not
intended for use on real Cirrus hardware.
config VGA_ATI
depends on QEMU
bool "QEMU ATI SVGA"
select VGA_STDVGA_PORTS
help
Build support for ATI VGA emulation found on QEMU
and emulators. This is for emulators; it is not
intended for use on real ATI hardware.
config VGA_BOCHS
depends on QEMU
bool "QEMU/Bochs VBE SVGA"
select VGA_STDVGA_PORTS
help
Build support for Bochs DISPI interface (a custom VBE
protocol) found on QEMU and Bochs emulators.
config VGA_GEODEGX2
bool "GeodeGX2"
select VGA_STDVGA_PORTS
help
Build support for Geode GX2 vga.
config VGA_GEODELX
bool "GeodeLX"
select VGA_STDVGA_PORTS
help
Build support for Geode LX vga.
config VGA_COREBOOT
depends on COREBOOT
bool "coreboot linear framebuffer"
select VGA_EMULATE_TEXT
help
Build support for a vgabios wrapper around video
devices initialized using coreboot native vga init.
config DISPLAY_BOCHS
depends on QEMU
bool "qemu bochs-display support"
select VGA_EMULATE_TEXT
help
Build support for the qemu bochs-display device, which
is basically qemu stdvga without the legacy vga
emulation, supporting only 16+32 bpp VESA video modes
in a linear framebuffer. So this uses cbvga text mode
emulation.
The bochs-display device is available in qemu
v3.0+. The vgabios works with the qemu stdvga too (use
"qemu -device VGA,romfile=/path/to/vgabios.bin")".
config VGA_RAMFB
depends on QEMU
bool "qemu ramfb"
select VGA_EMULATE_TEXT
help
qemu ram framebuffer support (-device ramfb).
endchoice
choice
depends on VGA_BOCHS
prompt "bochs vga variant"
default VGA_BOCHS_STDVGA
config VGA_BOCHS_STDVGA
bool "qemu stdvga / bochs svga"
config VGA_BOCHS_VMWARE
bool "qemu vmware svga"
config VGA_BOCHS_QXL
bool "qemu qxl vga"
config VGA_BOCHS_VIRTIO
bool "qemu virtio vga"
endchoice
choice
depends on VGA_GEODEGX2 || VGA_GEODELX
prompt "Output Mode"
default VGA_OUTPUT_CRT
config VGA_OUTPUT_CRT
bool "CRT"
help
Use CRT for output.
config VGA_OUTPUT_PANEL
bool "Flat Panel"
help
Use flat panel for output.
config VGA_OUTPUT_CRT_PANEL
bool "CRT and Flat Panel"
help
Use CRT and flat panel for output.
endchoice
config BUILD_VGABIOS
bool
default !NO_VGABIOS
config VGA_STDVGA_PORTS
bool
config VGA_EMULATE_TEXT
bool
help
Support emulating text mode features when only a
framebuffer is available.
config VGA_FIXUP_ASM
depends on BUILD_VGABIOS
bool "Fixup assembler to work with broken emulators"
default y
help
This option will cause the build to attempt to avoid
certain x86 machine instructions that are known to confuse
some emulators. In particular, it works around
deficiencies in the Windows vgabios emulator and the
x86emu vgabios emulator (frequently used in Xorg).
config VGA_ALLOCATE_EXTRA_STACK
depends on BUILD_VGABIOS
bool "Allocate an internal stack for 16bit interrupt entry point"
default y
help
Attempt to allocate (via BIOS PMM call) an internal stack
for the legacy 16bit 0x10 interrupt entry point. This
reduces the amount of space on the caller's stack that
SeaVGABIOS uses.
config VGA_EXTRA_STACK_SIZE
int
default 512
config VGA_VBE
depends on BUILD_VGABIOS
bool "Video BIOS Extensions (VBE)"
default y
help
Support VBE.
config VGA_PCI
depends on BUILD_VGABIOS && !VGA_COREBOOT
bool "PCI ROM Headers"
default y
help
Build PCI ROM headers so the vga rom can be extracted from
a PCI device.
config OVERRIDE_PCI_ID
depends on VGA_PCI
bool "Override PCI Vendor and Device IDs"
help
Specify specific values for the PCI Vendor and Device IDs.
config VGA_VID
depends on VGA_PCI
hex
prompt "PCI Vendor ID" if OVERRIDE_PCI_ID
default 0x1013 if VGA_CIRRUS
default 0x1002 if VGA_ATI
default 0x1234 if VGA_BOCHS_STDVGA
default 0x15ad if VGA_BOCHS_VMWARE
default 0x1b36 if VGA_BOCHS_QXL
default 0x1af4 if VGA_BOCHS_VIRTIO
default 0x100b if VGA_GEODEGX2
default 0x1022 if VGA_GEODELX
default 0x1234 if DISPLAY_BOCHS
default 0x0000
help
Vendor ID for the PCI ROM
config VGA_DID
depends on VGA_PCI
hex
prompt "PCI Vendor ID" if OVERRIDE_PCI_ID
default 0x00b8 if VGA_CIRRUS
default 0x5159 if VGA_ATI
default 0x1111 if VGA_BOCHS_STDVGA
default 0x0405 if VGA_BOCHS_VMWARE
default 0x0100 if VGA_BOCHS_QXL
default 0x1050 if VGA_BOCHS_VIRTIO
default 0x0030 if VGA_GEODEGX2
default 0x2081 if VGA_GEODELX
default 0x1111 if DISPLAY_BOCHS
default 0x0000
help
Device ID for the PCI ROM
endmenu
+43
View File
@@ -0,0 +1,43 @@
//
// Fake ati bios tables.
//
// aty128fb and radeonfb try to gather informations from these tables,
// so add some stuff here to make the drivers happy. Specifically
// radeonfb needs the pll information, otherwise it'll crash with a
// division by zero ...
//
.org 0x48
.word _ati_main
// main info
.org 0x50
_ati_main:
.org 0x50 + 0x30
.word _ati_pll
.org 0x50 + 0x50
.word _ati_connector
// pll info
.org 0x100
_ati_pll:
.word 0 // ??? (not used by radeonfb)
.word 0
.word 0
.word 0
.word 23000 // sclk
.word 23000 // mclk
.word 0
.word 2700 // ref_clk
.word 4 // ref_div
.long 12000 // ppll_min
.long 35000 // ppll_max
// connector info
.org 0x140
_ati_connector:
.byte 0x10 // one chip
.byte 0x01 // one connector
.word 0x3000 // type DVI-I
.word 0 // end of list
.org 0x200
+413
View File
@@ -0,0 +1,413 @@
// QEMU ATI VGABIOS Extension.
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_GLOBAL
#include "bregs.h" // struct bregs
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "output.h" // dprintf
#include "stdvga.h" // VGAREG_SEQU_ADDRESS
#include "string.h" // memset16_far
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // VBE_total_memory
#include "vgafb.h" // memset_high
#include "svgamodes.h"
#define MM_INDEX 0x0000
#define MM_DATA 0x0004
#define CRTC_GEN_CNTL 0x0050
#define CRTC_EXT_CNTL 0x0054
#define GPIO_VGA_DDC 0x0060
#define GPIO_DVI_DDC 0x0064
#define GPIO_MONID 0x0068
#define CRTC_H_TOTAL_DISP 0x0200
#define CRTC_V_TOTAL_DISP 0x0208
#define CRTC_OFFSET 0x0224
#define CRTC_PITCH 0x022c
/* CRTC control values (CRTC_GEN_CNTL) */
#define CRTC2_EXT_DISP_EN 0x01000000
#define CRTC2_EN 0x02000000
#define CRTC_PIX_WIDTH_MASK 0x00000700
#define CRTC_PIX_WIDTH_4BPP 0x00000100
#define CRTC_PIX_WIDTH_8BPP 0x00000200
#define CRTC_PIX_WIDTH_15BPP 0x00000300
#define CRTC_PIX_WIDTH_16BPP 0x00000400
#define CRTC_PIX_WIDTH_24BPP 0x00000500
#define CRTC_PIX_WIDTH_32BPP 0x00000600
/* CRTC_EXT_CNTL */
#define CRT_CRTC_DISPLAY_DIS 0x00000400
#define CRT_CRTC_ON 0x00008000
static u32 ati_io_addr VAR16 = 0;
static u32 ati_i2c_reg VAR16;
static u32 ati_i2c_bit_scl_out VAR16;
static u32 ati_i2c_bit_sda_out VAR16;
static u32 ati_i2c_bit_sda_in VAR16;
static u32 ati_i2c_bit_enable VAR16 = -1;
int
is_ati_mode(struct vgamode_s *vmode_g)
{
unsigned int mcount = GET_GLOBAL(svga_mcount);
return (vmode_g >= &svga_modes[0].info &&
vmode_g <= &svga_modes[mcount-1].info);
}
struct vgamode_s *
ati_find_mode(int mode)
{
u32 io_addr = GET_GLOBAL(ati_io_addr);
struct generic_svga_mode *table_g = svga_modes;
unsigned int mcount = GET_GLOBAL(svga_mcount);
if (io_addr) {
while (table_g < &svga_modes[mcount]) {
if (GET_GLOBAL(table_g->mode) == mode)
return &table_g->info;
table_g++;
}
}
return stdvga_find_mode(mode);
}
void
ati_list_modes(u16 seg, u16 *dest, u16 *last)
{
u32 io_addr = GET_GLOBAL(ati_io_addr);
unsigned int mcount = GET_GLOBAL(svga_mcount);
dprintf(1, "%s: ati ext %s\n", __func__, io_addr ? "yes" : "no");
if (io_addr) {
int i;
for (i=0; i<mcount && dest<last; i++) {
u16 mode = GET_GLOBAL(svga_modes[i].mode);
if (mode == 0xffff)
continue;
SET_FARVAR(seg, *dest, mode);
dest++;
}
}
stdvga_list_modes(seg, dest, last);
}
/****************************************************************
* Mode setting
****************************************************************/
static inline void ati_write(u32 reg, u32 val)
{
u32 io_addr = GET_GLOBAL(ati_io_addr);
if (reg < 0x100) {
outl(val, io_addr + reg);
} else {
outl(reg, io_addr + MM_INDEX);
outl(val, io_addr + MM_DATA);
}
}
static inline u32 ati_read(u32 reg)
{
u32 io_addr = GET_GLOBAL(ati_io_addr);
u32 val;
if (reg < 0x100) {
val = inl(io_addr + reg);
} else {
outl(reg, io_addr + MM_INDEX);
val = inl(io_addr + MM_DATA);
}
return val;
}
static void ati_clear(u32 offset, u32 size)
{
u8 data[64];
void *datap = MAKE_FLATPTR(GET_SEG(SS), data);
void *fb = (void*)(GET_GLOBAL(VBE_framebuffer) + offset);
u32 i, pos;
for (i = 0; i < sizeof(data); i++)
data[i] = 0;
for (pos = 0; pos < size; pos += sizeof(data)) {
memcpy_high(fb, datap, sizeof(data));
fb += sizeof(data);
}
}
static int
ati_ext_mode(struct generic_svga_mode *table, int flags)
{
u32 width = GET_GLOBAL(table->info.width);
u32 height = GET_GLOBAL(table->info.height);
u32 depth = GET_GLOBAL(table->info.depth);
u32 stride = width;
u32 offset = 0;
u32 pxmask = 0;
u32 bytes = 0;
dprintf(1, "%s: 0x%x, %dx%d-%d\n", __func__,
GET_GLOBAL(table->mode),
width, height, depth);
switch (depth) {
case 8: pxmask = CRTC_PIX_WIDTH_8BPP; bytes = 1; break;
case 15: pxmask = CRTC_PIX_WIDTH_15BPP; bytes = 2; break;
case 16: pxmask = CRTC_PIX_WIDTH_16BPP; bytes = 2; break;
case 24: pxmask = CRTC_PIX_WIDTH_24BPP; bytes = 3; break;
case 32: pxmask = CRTC_PIX_WIDTH_32BPP; bytes = 4; break;
}
/* disable display */
ati_write(CRTC_EXT_CNTL, CRT_CRTC_DISPLAY_DIS);
/* modeset */
ati_write(CRTC_GEN_CNTL, CRTC2_EXT_DISP_EN | CRTC2_EN | pxmask);
ati_write(CRTC_H_TOTAL_DISP, ((width / 8) - 1) << 16);
ati_write(CRTC_V_TOTAL_DISP, (height - 1) << 16);
ati_write(CRTC_OFFSET, offset);
ati_write(CRTC_PITCH, stride / 8);
/* clear screen */
if (!(flags & MF_NOCLEARMEM)) {
u32 size = width * height * bytes;
ati_clear(offset, size);
}
/* enable display */
ati_write(CRTC_EXT_CNTL, 0);
return 0;
}
int
ati_set_mode(struct vgamode_s *vmode_g, int flags)
{
struct generic_svga_mode *table_g =
container_of(vmode_g, struct generic_svga_mode, info);
if (is_ati_mode(vmode_g)) {
return ati_ext_mode(table_g, flags);
}
ati_write(CRTC_GEN_CNTL, 0);
return stdvga_set_mode(vmode_g, flags);
}
/****************************************************************
* edid
****************************************************************/
static void
ati_i2c_set_scl_sda(int scl, int sda)
{
u32 enable = GET_GLOBAL(ati_i2c_bit_enable);
u32 data = 0;
if (enable != -1)
data |= (1 << enable);
if (!scl)
data |= (1 << GET_GLOBAL(ati_i2c_bit_scl_out));
if (!sda)
data |= (1 << GET_GLOBAL(ati_i2c_bit_sda_out));
ati_write(GET_GLOBAL(ati_i2c_reg), data);
}
static int
ati_i2c_get_sda(void)
{
u32 data = ati_read(GET_GLOBAL(ati_i2c_reg));
return data & (1 << GET_GLOBAL(ati_i2c_bit_sda_in)) ? 1 : 0;
}
static void ati_i2c_start(void)
{
ati_i2c_set_scl_sda(1, 1);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(0, 0);
}
static void ati_i2c_ack(void)
{
ati_i2c_set_scl_sda(0, 0);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(0, 0);
}
static void ati_i2c_stop(void)
{
ati_i2c_set_scl_sda(0, 0);
ati_i2c_set_scl_sda(1, 0);
ati_i2c_set_scl_sda(1, 1);
}
static void ati_i2c_send_byte(u8 byte)
{
int i, bit;
for (i = 0; i < 8; i++) {
bit = (1 << (7-i)) & byte ? 1 : 0;
ati_i2c_set_scl_sda(0, bit);
ati_i2c_set_scl_sda(1, bit);
ati_i2c_set_scl_sda(0, bit);
}
}
static u8 ati_i2c_recv_byte(void)
{
u8 byte = 0;
int i, bit;
for (i = 0; i < 8; i++) {
ati_i2c_set_scl_sda(0, 1);
ati_i2c_set_scl_sda(1, 1);
bit = ati_i2c_get_sda();
ati_i2c_set_scl_sda(0, 1);
if (bit)
byte |= (1 << (7-i));
}
return byte;
}
static void ati_i2c_edid(void)
{
u8 byte;
int i;
ati_i2c_start();
ati_i2c_send_byte(0x50 << 1 | 1);
ati_i2c_ack();
for (i = 0; i < 128; i++) {
byte = ati_i2c_recv_byte();
ati_i2c_ack();
SET_VGA(VBE_edid[i], byte);
}
ati_i2c_stop();
}
static void ati_i2c_edid_radeon(void)
{
int valid;
SET_VGA(ati_i2c_bit_scl_out, 17);
SET_VGA(ati_i2c_bit_sda_out, 16);
SET_VGA(ati_i2c_bit_sda_in, 8);
dprintf(1, "ati: reading edid blob (radeon vga) ... \n");
SET_VGA(ati_i2c_reg, GPIO_VGA_DDC);
ati_i2c_edid();
valid = (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff);
dprintf(1, "ati: ... %s\n", valid ? "good" : "invalid");
if (valid)
return;
dprintf(1, "ati: reading edid blob (radeon dvi) ... \n");
SET_VGA(ati_i2c_reg, GPIO_DVI_DDC);
ati_i2c_edid();
valid = (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff);
dprintf(1, "ati: ... %s\n", valid ? "good" : "invalid");
}
static void ati_i2c_edid_rage128(void)
{
int valid;
SET_VGA(ati_i2c_bit_enable, 25);
SET_VGA(ati_i2c_bit_scl_out, 18);
SET_VGA(ati_i2c_bit_sda_out, 17);
SET_VGA(ati_i2c_bit_sda_in, 9);
SET_VGA(ati_i2c_reg, GPIO_MONID);
dprintf(1, "ati: reading edid blob (rage128) ... \n");
ati_i2c_edid();
valid = (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff);
dprintf(1, "ati: ... %s\n", valid ? "good" : "invalid");
}
/****************************************************************
* init
****************************************************************/
int
ati_setup(void)
{
int ret = stdvga_setup();
if (ret)
return ret;
dprintf(1, "%s:%d\n", __func__, __LINE__);
if (GET_GLOBAL(HaveRunInit))
return 0;
int bdf = GET_GLOBAL(VgaBDF);
if (!CONFIG_VGA_PCI || bdf == 0)
return 0;
u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
u32 lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK;
pci_config_writel(bdf, PCI_BASE_ADDRESS_0, ~0);
u32 barmask = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
u32 totalmem = ~(barmask & PCI_BASE_ADDRESS_MEM_MASK) + 1;
pci_config_writel(bdf, PCI_BASE_ADDRESS_0, bar);
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_1);
u32 io_addr = bar & PCI_BASE_ADDRESS_IO_MASK;
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2);
u32 mmio_addr = bar & PCI_BASE_ADDRESS_MEM_MASK;
dprintf(1, "ati: bdf %02x:%02x.%x, lfb 0x%x, %d MB, io 0x%x, mmio 0x%x\n",
pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
lfb_addr, totalmem / (1024 * 1024), io_addr, mmio_addr);
SET_VGA(VBE_framebuffer, lfb_addr);
SET_VGA(VBE_total_memory, totalmem);
SET_VGA(ati_io_addr, io_addr);
// Validate modes
struct generic_svga_mode *m = svga_modes;
unsigned int mcount = GET_GLOBAL(svga_mcount);
for (; m < &svga_modes[mcount]; m++) {
u8 memmodel = GET_GLOBAL(m->info.memmodel);
u16 width = GET_GLOBAL(m->info.width);
u16 height = GET_GLOBAL(m->info.height);
u32 mem = (height * DIV_ROUND_UP(width * vga_bpp(&m->info), 8)
* stdvga_vram_ratio(&m->info));
if (width % 8 != 0 ||
width > 0x7ff * 8 ||
height > 0xfff ||
mem > totalmem ||
memmodel != MM_DIRECT) {
dprintf(3, "ati: removing mode 0x%x\n", GET_GLOBAL(m->mode));
SET_VGA(m->mode, 0xffff);
}
}
u16 device = pci_config_readw(bdf, PCI_DEVICE_ID);
switch (device) {
case 0x5046:
ati_i2c_edid_rage128();
break;
case 0x5159:
ati_i2c_edid_radeon();
break;
}
return 0;
}
+79
View File
@@ -0,0 +1,79 @@
// Simple framebuffer vgabios for use with qemu bochs-display device
//
// Copyright (C) 2019 Gerd Hoffmann <kraxel@redhat.com>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_BDA
#include "output.h" // dprintf
#include "string.h" // memset16_far
#include "bochsvga.h" // VBE_BOCHS_*
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // VBE_total_memory
#define FRAMEBUFFER_WIDTH 1024
#define FRAMEBUFFER_HEIGHT 768
#define FRAMEBUFFER_BPP 4
int
bochs_display_setup(void)
{
dprintf(1, "bochs-display: setup called\n");
if (GET_GLOBAL(HaveRunInit))
return 0;
int bdf = GET_GLOBAL(VgaBDF);
if (bdf == 0)
return 0;
u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
u32 lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK;
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2);
u32 io_addr = bar & PCI_BASE_ADDRESS_IO_MASK;
dprintf(1, "bochs-display: bdf %02x:%02x.%x, bar 0 at 0x%x, bar 1 at 0x%x\n"
, pci_bdf_to_bus(bdf) , pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf),
lfb_addr, io_addr);
u16 *dispi = (void*)(io_addr + 0x500);
u8 *vga = (void*)(io_addr + 0x400);
u16 id = readw(dispi + VBE_DISPI_INDEX_ID);
dprintf(1, "bochs-display: id is 0x%x, %s\n", id
, id == VBE_DISPI_ID5 ? "good" : "FAIL");
if (id != VBE_DISPI_ID5)
return -1;
int i;
u8 *edid = (void*)(io_addr);
for (i = 0; i < sizeof(VBE_edid); i++)
SET_VGA(VBE_edid[i], readb(edid + i));
int fb_width = FRAMEBUFFER_WIDTH;
int fb_height = FRAMEBUFFER_HEIGHT;
if (GET_GLOBAL(VBE_edid[0]) == 0x00 &&
GET_GLOBAL(VBE_edid[1]) == 0xff) {
fb_width = GET_GLOBAL(VBE_edid[54 + 2]);
fb_width |= (GET_GLOBAL(VBE_edid[54 + 4]) & 0xf0) << 4;
fb_height = GET_GLOBAL(VBE_edid[54 + 5]);
fb_height |= (GET_GLOBAL(VBE_edid[54 + 7]) & 0xf0) << 4;
}
int fb_stride = FRAMEBUFFER_BPP * fb_width;
dprintf(1, "bochs-display: using %dx%d, %d bpp (%d stride)\n"
, fb_width, fb_height
, FRAMEBUFFER_BPP * 8, fb_stride);
cbvga_setup_modes(lfb_addr, FRAMEBUFFER_BPP * 8,
fb_width, fb_height, fb_stride);
writew(dispi + VBE_DISPI_INDEX_XRES, fb_width);
writew(dispi + VBE_DISPI_INDEX_YRES, fb_height);
writew(dispi + VBE_DISPI_INDEX_BPP, FRAMEBUFFER_BPP * 8);
writew(dispi + VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);
writeb(vga, 0x20); /* unblank (for qemu -device VGA) */
return 0;
}
+384
View File
@@ -0,0 +1,384 @@
// Bochs VGA interface to extended "VBE" modes
//
// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2011 Julian Pidancet <julian.pidancet@citrix.com>
// Copyright (C) 2002 Jeroen Janssen
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_GLOBAL
#include "bochsvga.h" // bochsvga_set_mode
#include "config.h" // CONFIG_*
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "output.h" // dprintf
#include "std/vbe.h" // VBE_CAPABILITY_8BIT_DAC
#include "stdvga.h" // stdvga_get_linelength
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // VBE_total_memory
#include "x86.h" // outw
/****************************************************************
* Mode tables
****************************************************************/
#include "svgamodes.h"
static int dispi_found VAR16 = 0;
static int is_bochsvga_mode(struct vgamode_s *vmode_g)
{
unsigned int mcount = GET_GLOBAL(svga_mcount);
return (vmode_g >= &svga_modes[0].info
&& vmode_g <= &svga_modes[mcount-1].info);
}
struct vgamode_s *bochsvga_find_mode(int mode)
{
struct generic_svga_mode *m = svga_modes;
unsigned int mcount = GET_GLOBAL(svga_mcount);
if (GET_GLOBAL(dispi_found))
for (; m < &svga_modes[mcount]; m++)
if (GET_GLOBAL(m->mode) == mode)
return &m->info;
return stdvga_find_mode(mode);
}
void
bochsvga_list_modes(u16 seg, u16 *dest, u16 *last)
{
struct generic_svga_mode *m = svga_modes;
unsigned int mcount = GET_GLOBAL(svga_mcount);
if (GET_GLOBAL(dispi_found)) {
for (; m < &svga_modes[mcount] && dest<last; m++) {
u16 mode = GET_GLOBAL(m->mode);
if (mode == 0xffff)
continue;
SET_FARVAR(seg, *dest, mode);
dest++;
}
}
stdvga_list_modes(seg, dest, last);
}
/****************************************************************
* Helper functions
****************************************************************/
static inline u16 dispi_read(u16 reg)
{
outw(reg, VBE_DISPI_IOPORT_INDEX);
return inw(VBE_DISPI_IOPORT_DATA);
}
static inline void dispi_write(u16 reg, u16 val)
{
outw(reg, VBE_DISPI_IOPORT_INDEX);
outw(val, VBE_DISPI_IOPORT_DATA);
}
static u8
bochsvga_dispi_enabled(void)
{
if (!GET_GLOBAL(dispi_found))
return 0;
u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
if (!(en & VBE_DISPI_ENABLED))
return 0;
return 1;
}
int
bochsvga_get_window(struct vgamode_s *curmode_g, int window)
{
if (!bochsvga_dispi_enabled())
return stdvga_get_window(curmode_g, window);
if (window != 0)
return -1;
return dispi_read(VBE_DISPI_INDEX_BANK);
}
int
bochsvga_set_window(struct vgamode_s *curmode_g, int window, int val)
{
if (!bochsvga_dispi_enabled())
return stdvga_set_window(curmode_g, window, val);
if (window != 0)
return -1;
dispi_write(VBE_DISPI_INDEX_BANK, val);
if (dispi_read(VBE_DISPI_INDEX_BANK) != val)
return -1;
return 0;
}
int
bochsvga_get_linelength(struct vgamode_s *curmode_g)
{
if (!bochsvga_dispi_enabled())
return stdvga_get_linelength(curmode_g);
return dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * vga_bpp(curmode_g) / 8;
}
int
bochsvga_set_linelength(struct vgamode_s *curmode_g, int val)
{
stdvga_set_linelength(curmode_g, val);
if (bochsvga_dispi_enabled()) {
int pixels = (val * 8) / vga_bpp(curmode_g);
dispi_write(VBE_DISPI_INDEX_VIRT_WIDTH, pixels);
}
return 0;
}
int
bochsvga_get_displaystart(struct vgamode_s *curmode_g)
{
if (!bochsvga_dispi_enabled())
return stdvga_get_displaystart(curmode_g);
int bpp = vga_bpp(curmode_g);
int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8;
int x = dispi_read(VBE_DISPI_INDEX_X_OFFSET);
int y = dispi_read(VBE_DISPI_INDEX_Y_OFFSET);
return x * bpp / 8 + linelength * y;
}
int
bochsvga_set_displaystart(struct vgamode_s *curmode_g, int val)
{
stdvga_set_displaystart(curmode_g, val);
if (bochsvga_dispi_enabled()) {
int bpp = vga_bpp(curmode_g);
int linelength = dispi_read(VBE_DISPI_INDEX_VIRT_WIDTH) * bpp / 8;
if (!linelength)
return 0;
dispi_write(VBE_DISPI_INDEX_X_OFFSET, (val % linelength) * 8 / bpp);
dispi_write(VBE_DISPI_INDEX_Y_OFFSET, val / linelength);
}
return 0;
}
int
bochsvga_get_dacformat(struct vgamode_s *curmode_g)
{
if (!bochsvga_dispi_enabled())
return stdvga_get_dacformat(curmode_g);
u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
return (en & VBE_DISPI_8BIT_DAC) ? 8 : 6;
}
int
bochsvga_set_dacformat(struct vgamode_s *curmode_g, int val)
{
if (!bochsvga_dispi_enabled())
return stdvga_set_dacformat(curmode_g, val);
u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
if (val == 6)
en &= ~VBE_DISPI_8BIT_DAC;
else if (val == 8)
en |= VBE_DISPI_8BIT_DAC;
else
return -1;
dispi_write(VBE_DISPI_INDEX_ENABLE, en);
return 0;
}
static int
bochsvga_save_state(u16 seg, u16 *info)
{
u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
SET_FARVAR(seg, *info, en);
info++;
if (!(en & VBE_DISPI_ENABLED))
return 0;
int i;
for (i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++)
if (i != VBE_DISPI_INDEX_ENABLE) {
u16 v = dispi_read(i);
SET_FARVAR(seg, *info, v);
info++;
}
return 0;
}
static int
bochsvga_restore_state(u16 seg, u16 *info)
{
u16 en = GET_FARVAR(seg, *info);
info++;
if (!(en & VBE_DISPI_ENABLED)) {
dispi_write(VBE_DISPI_INDEX_ENABLE, en);
return 0;
}
int i;
for (i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++)
if (i == VBE_DISPI_INDEX_ENABLE) {
dispi_write(i, en);
} else {
dispi_write(i, GET_FARVAR(seg, *info));
info++;
}
return 0;
}
int
bochsvga_save_restore(int cmd, u16 seg, void *data)
{
int ret = stdvga_save_restore(cmd, seg, data);
if (ret < 0 || !(cmd & SR_REGISTERS) || !GET_GLOBAL(dispi_found))
return ret;
u16 *info = (data + ret);
if (cmd & SR_SAVE)
bochsvga_save_state(seg, info);
if (cmd & SR_RESTORE)
bochsvga_restore_state(seg, info);
return ret + (VBE_DISPI_INDEX_Y_OFFSET-VBE_DISPI_INDEX_XRES+1)*sizeof(u16);
}
/****************************************************************
* Mode setting
****************************************************************/
int
bochsvga_set_mode(struct vgamode_s *vmode_g, int flags)
{
if (GET_GLOBAL(dispi_found))
dispi_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
if (! is_bochsvga_mode(vmode_g))
return stdvga_set_mode(vmode_g, flags);
if (!GET_GLOBAL(dispi_found))
return -1;
u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
if (memmodel == MM_PLANAR)
stdvga_set_mode(stdvga_find_mode(0x6a), 0);
if (memmodel == MM_PACKED && !(flags & MF_NOPALETTE))
stdvga_set_packed_palette();
dispi_write(VBE_DISPI_INDEX_BPP, GET_GLOBAL(vmode_g->depth));
u16 width = GET_GLOBAL(vmode_g->width);
u16 height = GET_GLOBAL(vmode_g->height);
dispi_write(VBE_DISPI_INDEX_XRES, width);
dispi_write(VBE_DISPI_INDEX_YRES, height);
dispi_write(VBE_DISPI_INDEX_BANK, 0);
u16 bf = ((flags & MF_NOCLEARMEM ? VBE_DISPI_NOCLEARMEM : 0)
| (flags & MF_LINEARFB ? VBE_DISPI_LFB_ENABLED : 0));
dispi_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | bf);
/* VGA compat setup */
u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
stdvga_crtc_write(crtc_addr, 0x11, 0x00);
stdvga_crtc_write(crtc_addr, 0x01, width / 8 - 1);
stdvga_set_linelength(vmode_g, width);
stdvga_set_vertical_size(height);
stdvga_crtc_write(crtc_addr, 0x09, 0x00);
stdvga_crtc_mask(crtc_addr, 0x17, 0x00, 0x03);
stdvga_attr_mask(0x10, 0x00, 0x01);
stdvga_grdc_write(0x06, 0x05);
stdvga_sequ_write(0x02, 0x0f);
if (memmodel != MM_PLANAR) {
stdvga_crtc_mask(crtc_addr, 0x14, 0x00, 0x40);
stdvga_attr_mask(0x10, 0x00, 0x40);
stdvga_sequ_mask(0x04, 0x00, 0x08);
stdvga_grdc_mask(0x05, 0x20, 0x40);
}
stdvga_attrindex_write(0x20);
return 0;
}
/****************************************************************
* Init
****************************************************************/
int
bochsvga_setup(void)
{
int ret = stdvga_setup();
if (ret)
return ret;
/* Sanity checks */
dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID0);
if (dispi_read(VBE_DISPI_INDEX_ID) != VBE_DISPI_ID0) {
dprintf(1, "No VBE DISPI interface detected, falling back to stdvga\n");
return 0;
}
dispi_write(VBE_DISPI_INDEX_ID, VBE_DISPI_ID5);
SET_VGA(dispi_found, 1);
if (GET_GLOBAL(HaveRunInit))
return 0;
u32 lfb_addr = VBE_DISPI_LFB_PHYSICAL_ADDRESS;
u32 io_addr = 0;
int bdf = GET_GLOBAL(VgaBDF);
if (CONFIG_VGA_PCI && bdf >= 0) {
u16 vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
int barid, bar;
switch (vendor) {
case 0x15ad: /* qemu vmware vga */
barid = 1;
break;
case 0x1234: /* stdvga */
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_2);
io_addr = bar & PCI_BASE_ADDRESS_IO_MASK;
barid = 0;
break;
default: /* qxl, virtio */
barid = 0;
break;
}
bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_0 + barid * 4);
lfb_addr = bar & PCI_BASE_ADDRESS_MEM_MASK;
dprintf(1, "VBE DISPI: bdf %02x:%02x.%x, bar %d\n", pci_bdf_to_bus(bdf)
, pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf), barid);
}
SET_VGA(VBE_framebuffer, lfb_addr);
u32 totalmem = dispi_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
SET_VGA(VBE_total_memory, totalmem);
SET_VGA(VBE_win_granularity, 64);
SET_VGA(VBE_capabilities, VBE_CAPABILITY_8BIT_DAC);
dprintf(1, "VBE DISPI: lfb_addr=%x, size %d MB\n",
lfb_addr, totalmem >> 20);
// Validate modes
u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
dispi_write(VBE_DISPI_INDEX_ENABLE, en | VBE_DISPI_GETCAPS);
u16 max_xres = dispi_read(VBE_DISPI_INDEX_XRES);
u16 max_bpp = dispi_read(VBE_DISPI_INDEX_BPP);
dispi_write(VBE_DISPI_INDEX_ENABLE, en);
struct generic_svga_mode *m = svga_modes;
unsigned int mcount = GET_GLOBAL(svga_mcount);
for (; m < &svga_modes[mcount]; m++) {
u16 width = GET_GLOBAL(m->info.width);
u16 height = GET_GLOBAL(m->info.height);
u8 depth = GET_GLOBAL(m->info.depth);
u32 mem = (height * DIV_ROUND_UP(width * vga_bpp(&m->info), 8)
* stdvga_vram_ratio(&m->info));
if (width > max_xres || depth > max_bpp || mem > totalmem) {
dprintf(1, "Removing mode %x\n", GET_GLOBAL(m->mode));
SET_VGA(m->mode, 0xffff);
}
}
if (io_addr) {
int i;
u8 *edid = (void*)(io_addr);
for (i = 0; i < sizeof(VBE_edid); i++)
SET_VGA(VBE_edid[i], readb(edid + i));
}
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef __BOCHSVGA_H
#define __BOCHSVGA_H
#include "types.h" // u8
#define VBE_DISPI_BANK_ADDRESS 0xA0000
#define VBE_DISPI_BANK_SIZE_KB 64
#define VBE_DISPI_MAX_XRES 2560
#define VBE_DISPI_MAX_YRES 1600
#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA 0x01CF
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
#define VBE_DISPI_ID0 0xB0C0
#define VBE_DISPI_ID1 0xB0C1
#define VBE_DISPI_ID2 0xB0C2
#define VBE_DISPI_ID3 0xB0C3
#define VBE_DISPI_ID4 0xB0C4
#define VBE_DISPI_ID5 0xB0C5
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_GETCAPS 0x02
#define VBE_DISPI_8BIT_DAC 0x20
#define VBE_DISPI_LFB_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
struct vgamode_s *bochsvga_find_mode(int mode);
void bochsvga_list_modes(u16 seg, u16 *dest, u16 *last);
int bochsvga_get_window(struct vgamode_s *curmode_g, int window);
int bochsvga_set_window(struct vgamode_s *curmode_g, int window, int val);
int bochsvga_get_linelength(struct vgamode_s *curmode_g);
int bochsvga_set_linelength(struct vgamode_s *curmode_g, int val);
int bochsvga_get_displaystart(struct vgamode_s *curmode_g);
int bochsvga_set_displaystart(struct vgamode_s *curmode_g, int val);
int bochsvga_get_dacformat(struct vgamode_s *curmode_g);
int bochsvga_set_dacformat(struct vgamode_s *curmode_g, int val);
int bochsvga_save_restore(int cmd, u16 seg, void *data);
int bochsvga_set_mode(struct vgamode_s *vmode_g, int flags);
int bochsvga_setup(void);
#endif // bochsvga.h
+275
View File
@@ -0,0 +1,275 @@
// Simple framebuffer vgabios for use with coreboot native vga init.
//
// Copyright (C) 2014 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_BDA
#include "output.h" // dprintf
#include "stdvga.h" // SEG_CTEXT
#include "string.h" // memset16_far
#include "util.h" // find_cb_table
#include "vgabios.h" // SET_VGA
#include "vgafb.h" // handle_gfx_op
#include "vgautil.h" // VBE_total_memory
#include "svgamodes.h" // svga_modes
static int CBmode VAR16;
static struct vgamode_s CBmodeinfo VAR16;
static struct vgamode_s CBemulinfo VAR16;
static u32 CBlinelength VAR16;
struct vgamode_s *cbvga_find_mode(int mode)
{
if (mode == GET_GLOBAL(CBmode))
return &CBmodeinfo;
if (mode == 0x03)
return &CBemulinfo;
int i;
for (i = 0; i < GET_GLOBAL(svga_mcount); i++) {
struct generic_svga_mode *cbmode_g = &svga_modes[i];
if (GET_GLOBAL(cbmode_g->mode) == 0xffff)
continue;
if (GET_GLOBAL(cbmode_g->mode) == mode)
return &cbmode_g->info;
}
return NULL;
}
void
cbvga_list_modes(u16 seg, u16 *dest, u16 *last)
{
int seen = 0;
if (GET_GLOBAL(CBmode) != 0x3) {
/* Advertise additional SVGA modes for Microsoft NTLDR graphical mode.
* Microsoft NTLDR:
* + Graphical mode uses a maximum resolution of 1600x1200.
* + Expects to find VESA mode with 800x600 or 1024x768.
* + 24 Bpp and 32 Bpp are supported
*/
int i;
for (i = 0; i < GET_GLOBAL(svga_mcount) && dest < last; i++) {
struct generic_svga_mode *cbmode_g = &svga_modes[i];
u16 mode = GET_GLOBAL(cbmode_g->mode);
if (mode == 0xffff)
continue;
SET_FARVAR(seg, *dest, mode);
dest++;
if (GET_GLOBAL(CBmode) == mode)
seen = 1;
}
}
if (dest < last && !seen) {
SET_FARVAR(seg, *dest, GET_GLOBAL(CBmode));
dest++;
}
SET_FARVAR(seg, *dest, 0xffff);
}
int
cbvga_get_window(struct vgamode_s *curmode_g, int window)
{
return -1;
}
int
cbvga_set_window(struct vgamode_s *curmode_g, int window, int val)
{
return -1;
}
int
cbvga_minimum_linelength(struct vgamode_s *vmode_g)
{
/* Can't change mode, always report active pitch. */
return GET_GLOBAL(CBlinelength);
}
int
cbvga_get_linelength(struct vgamode_s *curmode_g)
{
return GET_GLOBAL(CBlinelength);
}
int
cbvga_set_linelength(struct vgamode_s *curmode_g, int val)
{
return -1;
}
int
cbvga_get_displaystart(struct vgamode_s *curmode_g)
{
return 0;
}
int
cbvga_set_displaystart(struct vgamode_s *curmode_g, int val)
{
return -1;
}
int
cbvga_get_dacformat(struct vgamode_s *curmode_g)
{
return -1;
}
int
cbvga_set_dacformat(struct vgamode_s *curmode_g, int val)
{
return -1;
}
int
cbvga_save_restore(int cmd, u16 seg, void *data)
{
if (cmd & (SR_HARDWARE|SR_DAC|SR_REGISTERS))
return -1;
return bda_save_restore(cmd, seg, data);
}
int
cbvga_set_mode(struct vgamode_s *vmode_g, int flags)
{
u8 emul = vmode_g == &CBemulinfo || GET_GLOBAL(CBmode) == 0x03;
/*
* The extra_stack flag is false when running in windows x86
* emulator, to avoid stack switching triggering bugs. Using the
* same flag here to skip screen clearing, because the windows
* emulator seems to have problems to handle the int 1587 call
* too, and GO_MEMSET uses that.
*/
u8 extra_stack = GET_BDA_EXT(flags) & BF_EXTRA_STACK;
MASK_BDA_EXT(flags, BF_EMULATE_TEXT, emul ? BF_EMULATE_TEXT : 0);
if (!(flags & MF_NOCLEARMEM)) {
if (GET_GLOBAL(CBmodeinfo.memmodel) == MM_TEXT) {
memset16_far(SEG_CTEXT, (void*)0, 0x0720, 80*25*2);
return 0;
}
if (extra_stack || flags & MF_LEGACY) {
struct gfx_op op;
init_gfx_op(&op, &CBmodeinfo);
op.x = op.y = 0;
op.xlen = GET_GLOBAL(CBmodeinfo.width);
op.ylen = GET_GLOBAL(CBmodeinfo.height);
op.op = GO_MEMSET;
handle_gfx_op(&op);
}
}
return 0;
}
#define CB_TAG_FRAMEBUFFER 0x0012
struct cb_framebuffer {
u32 tag;
u32 size;
u64 physical_address;
u32 x_resolution;
u32 y_resolution;
u32 bytes_per_line;
u8 bits_per_pixel;
u8 red_mask_pos;
u8 red_mask_size;
u8 green_mask_pos;
u8 green_mask_size;
u8 blue_mask_pos;
u8 blue_mask_size;
u8 reserved_mask_pos;
u8 reserved_mask_size;
};
void
cbvga_setup_modes(u64 addr, u8 bpp, u32 xlines, u32 ylines, u32 linelength)
{
int i;
SET_VGA(CBmode, 0x140);
SET_VGA(VBE_framebuffer, addr);
SET_VGA(VBE_total_memory, linelength * ylines);
SET_VGA(CBlinelength, linelength);
SET_VGA(CBmodeinfo.memmodel, MM_DIRECT);
SET_VGA(CBmodeinfo.width, xlines);
SET_VGA(CBmodeinfo.height, ylines);
SET_VGA(CBmodeinfo.depth, bpp);
SET_VGA(CBmodeinfo.cwidth, 8);
SET_VGA(CBmodeinfo.cheight, 16);
memcpy_far(get_global_seg(), &CBemulinfo
, get_global_seg(), &CBmodeinfo, sizeof(CBemulinfo));
// Validate modes
for (i = 0; i < GET_GLOBAL(svga_mcount); i++) {
struct generic_svga_mode *cbmode_g = &svga_modes[i];
/* Skip VBE modes that doesn't fit into coreboot's framebuffer */
if ((GET_GLOBAL(cbmode_g->info.memmodel) != MM_DIRECT)
|| (GET_GLOBAL(cbmode_g->info.height) > ylines)
|| (GET_GLOBAL(cbmode_g->info.width) > xlines)
|| (GET_GLOBAL(cbmode_g->info.depth) != bpp)) {
dprintf(3, "Removing mode %x\n", GET_GLOBAL(cbmode_g->mode));
SET_VGA(cbmode_g->mode, 0xffff);
}
if ((GET_GLOBAL(cbmode_g->info.height) == ylines)
&& (GET_GLOBAL(cbmode_g->info.width) == xlines)
&& (GET_GLOBAL(cbmode_g->info.depth) == bpp)) {
SET_VGA(CBmode, GET_GLOBAL(cbmode_g->mode));
}
}
}
int
cbvga_setup(void)
{
dprintf(1, "coreboot vga init\n");
if (GET_GLOBAL(HaveRunInit))
return 0;
struct cb_header *cbh = find_cb_table();
if (!cbh) {
dprintf(1, "Unable to find coreboot table\n");
return -1;
}
struct cb_framebuffer *cbfb = find_cb_subtable(cbh, CB_TAG_FRAMEBUFFER);
if (!cbfb) {
// Assume there is an EGA text framebuffer.
dprintf(1, "Did not find coreboot framebuffer - assuming EGA text\n");
SET_VGA(CBmode, 0x03);
SET_VGA(CBlinelength, 80*2);
SET_VGA(CBmodeinfo.memmodel, MM_TEXT);
SET_VGA(CBmodeinfo.width, 80);
SET_VGA(CBmodeinfo.height, 25);
SET_VGA(CBmodeinfo.depth, 4);
SET_VGA(CBmodeinfo.cwidth, 9);
SET_VGA(CBmodeinfo.cheight, 16);
SET_VGA(CBmodeinfo.sstart, SEG_CTEXT);
return 0;
}
u64 addr = GET_FARVAR(0, cbfb->physical_address);
u8 bpp = GET_FARVAR(0, cbfb->blue_mask_size)
+ GET_FARVAR(0, cbfb->green_mask_size)
+ GET_FARVAR(0, cbfb->red_mask_size)
+ GET_FARVAR(0, cbfb->reserved_mask_size);
u32 xlines = GET_FARVAR(0, cbfb->x_resolution);
u32 ylines = GET_FARVAR(0, cbfb->y_resolution);
u32 linelength = GET_FARVAR(0, cbfb->bytes_per_line);
//fall back to coreboot reported bpp if calculated value invalid
if (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32)
bpp = GET_FARVAR(0, cbfb->bits_per_pixel);
dprintf(1, "Found FB @ %llx %dx%d with %d bpp (%d stride)\n"
, addr, xlines, ylines, bpp, linelength);
if (!addr || addr > 0xffffffff
|| (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32)) {
dprintf(1, "Unable to use FB\n");
return -1;
}
cbvga_setup_modes(addr, bpp, xlines, ylines, linelength);
return 0;
}
+627
View File
@@ -0,0 +1,627 @@
// QEMU Cirrus CLGD 54xx VGABIOS Extension.
//
// Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
// Copyright (c) 2004 Makoto Suzuki (suzu)
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_GLOBAL
#include "bregs.h" // struct bregs
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "output.h" // dprintf
#include "stdvga.h" // VGAREG_SEQU_ADDRESS
#include "string.h" // memset16_far
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // VBE_total_memory
/****************************************************************
* Cirrus mode tables
****************************************************************/
/* VGA */
static u16 cseq_vga[] VAR16 = {0x0007,0xffff};
static u16 cgraph_vga[] VAR16 = {0x0009,0x000a,0x000b,0xffff};
static u16 ccrtc_vga[] VAR16 = {0x001a,0x001b,0x001d,0xffff};
/* extensions */
static u16 cgraph_svgacolor[] VAR16 = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08,
0x0009,0x000a,0x000b,
0xffff
};
/* 640x480x8 */
static u16 cseq_640x480x8[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
0x580b,0x580c,0x580d,0x580e,
0x0412,0x0013,0x2017,
0x331b,0x331c,0x331d,0x331e,
0xffff
};
static u16 ccrtc_640x480x8[] VAR16 = {
0x2c11,
0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
0x4009,0x000c,0x000d,
0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 640x480x16 */
static u16 cseq_640x480x16[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
0x580b,0x580c,0x580d,0x580e,
0x0412,0x0013,0x2017,
0x331b,0x331c,0x331d,0x331e,
0xffff
};
static u16 ccrtc_640x480x16[] VAR16 = {
0x2c11,
0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
0x4009,0x000c,0x000d,
0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 640x480x24 */
static u16 cseq_640x480x24[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
0x580b,0x580c,0x580d,0x580e,
0x0412,0x0013,0x2017,
0x331b,0x331c,0x331d,0x331e,
0xffff
};
static u16 ccrtc_640x480x24[] VAR16 = {
0x2c11,
0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
0x4009,0x000c,0x000d,
0xea10,0xdf12,0xf013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 800x600x8 */
static u16 cseq_800x600x8[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
0x230b,0x230c,0x230d,0x230e,
0x0412,0x0013,0x2017,
0x141b,0x141c,0x141d,0x141e,
0xffff
};
static u16 ccrtc_800x600x8[] VAR16 = {
0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
0x6009,0x000c,0x000d,
0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 800x600x16 */
static u16 cseq_800x600x16[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
0x230b,0x230c,0x230d,0x230e,
0x0412,0x0013,0x2017,
0x141b,0x141c,0x141d,0x141e,
0xffff
};
static u16 ccrtc_800x600x16[] VAR16 = {
0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
0x6009,0x000c,0x000d,
0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 800x600x24 */
static u16 cseq_800x600x24[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
0x230b,0x230c,0x230d,0x230e,
0x0412,0x0013,0x2017,
0x141b,0x141c,0x141d,0x141e,
0xffff
};
static u16 ccrtc_800x600x24[] VAR16 = {
0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
0x6009,0x000c,0x000d,
0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18,
0x001a,0x321b,0x001d,
0xffff
};
/* 1024x768x8 */
static u16 cseq_1024x768x8[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
0x760b,0x760c,0x760d,0x760e,
0x0412,0x0013,0x2017,
0x341b,0x341c,0x341d,0x341e,
0xffff
};
static u16 ccrtc_1024x768x8[] VAR16 = {
0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
0x6009,0x000c,0x000d,
0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 1024x768x16 */
static u16 cseq_1024x768x16[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
0x760b,0x760c,0x760d,0x760e,
0x0412,0x0013,0x2017,
0x341b,0x341c,0x341d,0x341e,
0xffff
};
static u16 ccrtc_1024x768x16[] VAR16 = {
0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
0x6009,0x000c,0x000d,
0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18,
0x001a,0x321b,0x001d,
0xffff
};
/* 1024x768x24 */
static u16 cseq_1024x768x24[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
0x760b,0x760c,0x760d,0x760e,
0x0412,0x0013,0x2017,
0x341b,0x341c,0x341d,0x341e,
0xffff
};
static u16 ccrtc_1024x768x24[] VAR16 = {
0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
0x6009,0x000c,0x000d,
0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
0x001a,0x321b,0x001d,
0xffff
};
/* 1280x1024x8 */
static u16 cseq_1280x1024x8[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
0x760b,0x760c,0x760d,0x760e,
0x0412,0x0013,0x2017,
0x341b,0x341c,0x341d,0x341e,
0xffff
};
static u16 ccrtc_1280x1024x8[] VAR16 = {
0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
0x6009,0x000c,0x000d,
0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
/* 1280x1024x16 */
static u16 cseq_1280x1024x16[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
0x760b,0x760c,0x760d,0x760e,
0x0412,0x0013,0x2017,
0x341b,0x341c,0x341d,0x341e,
0xffff
};
static u16 ccrtc_1280x1024x16[] VAR16 = {
0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
0x6009,0x000c,0x000d,
0x0310,0xff12,0x4013,0x4014,0xff15,0x2416,0xc317,0xff18,
0x001a,0x321b,0x001d,
0xffff
};
/* 1600x1200x8 */
static u16 cseq_1600x1200x8[] VAR16 = {
0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
0x760b,0x760c,0x760d,0x760e,
0x0412,0x0013,0x2017,
0x341b,0x341c,0x341d,0x341e,
0xffff
};
static u16 ccrtc_1600x1200x8[] VAR16 = {
0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
0x6009,0x000c,0x000d,
0x0310,0xff12,0xc813,0x4014,0xff15,0x2416,0xc317,0xff18,
0x001a,0x221b,0x001d,
0xffff
};
struct cirrus_mode_s {
u16 mode, vesamode;
struct vgamode_s info;
u16 hidden_dac; /* 0x3c6 */
u16 *seq; /* 0x3c4 */
u16 *graph; /* 0x3ce */
u16 *crtc; /* 0x3d4 */
};
static struct cirrus_mode_s cirrus_modes[] VAR16 = {
{0x5f,0x101,{MM_PACKED,640,480,8,8,16,SEG_GRAPH},0x00,
cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8},
{0x64,0x111,{MM_DIRECT,640,480,16,8,16,SEG_GRAPH},0xe1,
cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16},
{0x66,0x110,{MM_DIRECT,640,480,15,8,16,SEG_GRAPH},0xf0,
cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16},
{0x71,0x112,{MM_DIRECT,640,480,24,8,16,SEG_GRAPH},0xe5,
cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24},
{0x5c,0x103,{MM_PACKED,800,600,8,8,16,SEG_GRAPH},0x00,
cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8},
{0x65,0x114,{MM_DIRECT,800,600,16,8,16,SEG_GRAPH},0xe1,
cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16},
{0x67,0x113,{MM_DIRECT,800,600,15,8,16,SEG_GRAPH},0xf0,
cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16},
{0x60,0x105,{MM_PACKED,1024,768,8,8,16,SEG_GRAPH},0x00,
cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8},
{0x74,0x117,{MM_DIRECT,1024,768,16,8,16,SEG_GRAPH},0xe1,
cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16},
{0x68,0x116,{MM_DIRECT,1024,768,15,8,16,SEG_GRAPH},0xf0,
cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16},
{0x78,0x115,{MM_DIRECT,800,600,24,8,16,SEG_GRAPH},0xe5,
cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24},
{0x79,0x118,{MM_DIRECT,1024,768,24,8,16,SEG_GRAPH},0xe5,
cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24},
{0x6d,0x107,{MM_PACKED,1280,1024,8,8,16,SEG_GRAPH},0x00,
cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8},
{0x69,0x119,{MM_DIRECT,1280,1024,15,8,16,SEG_GRAPH},0xf0,
cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16},
{0x75,0x11a,{MM_DIRECT,1280,1024,16,8,16,SEG_GRAPH},0xe1,
cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16},
{0x7b,0xffff,{MM_PACKED,1600,1200,8,8,16,SEG_GRAPH},0x00,
cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8},
};
static struct cirrus_mode_s mode_switchback VAR16 =
{0xfe,0xffff,{0xff},0,cseq_vga,cgraph_vga,ccrtc_vga};
int
is_cirrus_mode(struct vgamode_s *vmode_g)
{
return (vmode_g >= &cirrus_modes[0].info
&& vmode_g <= &cirrus_modes[ARRAY_SIZE(cirrus_modes)-1].info);
}
struct vgamode_s *
clext_find_mode(int mode)
{
struct cirrus_mode_s *table_g = cirrus_modes;
while (table_g < &cirrus_modes[ARRAY_SIZE(cirrus_modes)]) {
if (GET_GLOBAL(table_g->mode) == mode
|| GET_GLOBAL(table_g->vesamode) == mode)
return &table_g->info;
table_g++;
}
return stdvga_find_mode(mode);
}
void
clext_list_modes(u16 seg, u16 *dest, u16 *last)
{
int i;
for (i=0; i<ARRAY_SIZE(cirrus_modes) && dest<last; i++) {
u16 mode = GET_GLOBAL(cirrus_modes[i].vesamode);
if (mode == 0xffff)
continue;
SET_FARVAR(seg, *dest, mode);
dest++;
}
stdvga_list_modes(seg, dest, last);
}
/****************************************************************
* helper functions
****************************************************************/
int
clext_get_window(struct vgamode_s *curmode_g, int window)
{
return stdvga_grdc_read(window + 9);
}
int
clext_set_window(struct vgamode_s *curmode_g, int window, int val)
{
if (val >= 0x100)
return -1;
stdvga_grdc_write(window + 9, val);
return 0;
}
int
clext_get_linelength(struct vgamode_s *curmode_g)
{
u16 crtc_addr = stdvga_get_crtc();
u8 reg13 = stdvga_crtc_read(crtc_addr, 0x13);
u8 reg1b = stdvga_crtc_read(crtc_addr, 0x1b);
return (((reg1b & 0x10) << 4) + reg13) * 8 / stdvga_vram_ratio(curmode_g);
}
int
clext_set_linelength(struct vgamode_s *curmode_g, int val)
{
u16 crtc_addr = stdvga_get_crtc();
val = DIV_ROUND_UP(val * stdvga_vram_ratio(curmode_g), 8);
stdvga_crtc_write(crtc_addr, 0x13, val);
stdvga_crtc_mask(crtc_addr, 0x1b, 0x10, (val & 0x100) >> 4);
return 0;
}
int
clext_get_displaystart(struct vgamode_s *curmode_g)
{
u16 crtc_addr = stdvga_get_crtc();
u8 b2 = stdvga_crtc_read(crtc_addr, 0x0c);
u8 b1 = stdvga_crtc_read(crtc_addr, 0x0d);
u8 b3 = stdvga_crtc_read(crtc_addr, 0x1b);
u8 b4 = stdvga_crtc_read(crtc_addr, 0x1d);
int val = (b1 | (b2<<8) | ((b3 & 0x01) << 16) | ((b3 & 0x0c) << 15)
| ((b4 & 0x80) << 12));
return val * 4 / stdvga_vram_ratio(curmode_g);
}
int
clext_set_displaystart(struct vgamode_s *curmode_g, int val)
{
u16 crtc_addr = stdvga_get_crtc();
val = val * stdvga_vram_ratio(curmode_g) / 4;
stdvga_crtc_write(crtc_addr, 0x0d, val);
stdvga_crtc_write(crtc_addr, 0x0c, val >> 8);
stdvga_crtc_mask(crtc_addr, 0x1d, 0x80, (val & 0x0800) >> 4);
stdvga_crtc_mask(crtc_addr, 0x1b, 0x0d
, ((val & 0x0100) >> 8) | ((val & 0x0600) >> 7));
return 0;
}
int
clext_save_restore(int cmd, u16 seg, void *data)
{
if (cmd & SR_REGISTERS)
return -1;
return stdvga_save_restore(cmd, seg, data);
}
/****************************************************************
* Mode setting
****************************************************************/
static void
cirrus_switch_mode_setregs(u16 *data, u16 port)
{
for (;;) {
u16 val = GET_GLOBAL(*data);
if (val == 0xffff)
return;
outw(val, port);
data++;
}
}
static void
cirrus_switch_mode(struct cirrus_mode_s *table)
{
// Unlock cirrus special
stdvga_sequ_write(0x06, 0x12);
cirrus_switch_mode_setregs(GET_GLOBAL(table->seq), VGAREG_SEQU_ADDRESS);
cirrus_switch_mode_setregs(GET_GLOBAL(table->graph), VGAREG_GRDC_ADDRESS);
cirrus_switch_mode_setregs(GET_GLOBAL(table->crtc), stdvga_get_crtc());
stdvga_pelmask_write(0x00);
stdvga_pelmask_read();
stdvga_pelmask_read();
stdvga_pelmask_read();
stdvga_pelmask_read();
stdvga_pelmask_write(GET_GLOBAL(table->hidden_dac));
stdvga_pelmask_write(0xff);
u8 memmodel = GET_GLOBAL(table->info.memmodel);
u8 on = 0;
if (memmodel == MM_PLANAR)
on = 0x41;
else if (memmodel != MM_TEXT)
on = 0x01;
stdvga_attr_mask(0x10, 0x01, on);
stdvga_attrindex_write(0x20);
}
static void
cirrus_enable_16k_granularity(void)
{
stdvga_grdc_mask(0x0b, 0x00, 0x20);
}
static void
cirrus_clear_vram(u16 fill)
{
cirrus_enable_16k_granularity();
int count = GET_GLOBAL(VBE_total_memory) / (16 * 1024);
int i;
for (i=0; i<count; i++) {
stdvga_grdc_write(0x09, i);
memset16_far(SEG_GRAPH, 0, fill, 16 * 1024);
}
stdvga_grdc_write(0x09, 0x00);
}
int
clext_set_mode(struct vgamode_s *vmode_g, int flags)
{
if (!is_cirrus_mode(vmode_g)) {
cirrus_switch_mode(&mode_switchback);
dprintf(1, "cirrus mode switch regular\n");
return stdvga_set_mode(vmode_g, flags);
}
struct cirrus_mode_s *table_g = container_of(
vmode_g, struct cirrus_mode_s, info);
cirrus_switch_mode(table_g);
if (GET_GLOBAL(vmode_g->memmodel) == MM_PACKED && !(flags & MF_NOPALETTE))
stdvga_set_packed_palette();
if (!(flags & MF_LINEARFB))
cirrus_enable_16k_granularity();
if (!(flags & MF_NOCLEARMEM))
// fill with 0xff to keep win 2K happy
cirrus_clear_vram(flags & MF_LEGACY ? 0xffff : 0x0000);
return 0;
}
/****************************************************************
* extbios
****************************************************************/
static void
clext_101280(struct bregs *regs)
{
u8 v = stdvga_crtc_read(stdvga_get_crtc(), 0x27);
if (v == 0xa0)
// 5430
regs->ax = 0x0032;
else if (v == 0xb8)
// 5446
regs->ax = 0x0039;
else
regs->ax = 0x00ff;
regs->bx = 0x00;
return;
}
static void
clext_101281(struct bregs *regs)
{
// XXX
regs->ax = 0x0100;
}
static void
clext_101282(struct bregs *regs)
{
regs->al = stdvga_crtc_read(stdvga_get_crtc(), 0x27) & 0x03;
regs->ah = 0xAF;
}
static void
clext_101285(struct bregs *regs)
{
regs->al = GET_GLOBAL(VBE_total_memory) / (64*1024);
}
static void
clext_10129a(struct bregs *regs)
{
regs->ax = 0x4060;
regs->cx = 0x1132;
}
extern void a0h_callback(void);
ASM16(
// fatal: not implemented yet
"a0h_callback:"
"cli\n"
"hlt\n"
"lretw");
static void
clext_1012a0(struct bregs *regs)
{
struct vgamode_s *table_g = clext_find_mode(regs->al & 0x7f);
regs->ah = (table_g ? 1 : 0);
regs->bx = (u32)a0h_callback;
regs->ds = regs->si = regs->es = regs->di = 0xffff;
}
static void
clext_1012a1(struct bregs *regs)
{
regs->bx = 0x0e00; // IBM 8512/8513, color
}
static void
clext_1012a2(struct bregs *regs)
{
regs->al = 0x07; // HSync 31.5 - 64.0 kHz
}
static void
clext_1012ae(struct bregs *regs)
{
regs->al = 0x01; // High Refresh 75Hz
}
static void
clext_1012XX(struct bregs *regs)
{
debug_stub(regs);
}
void
clext_1012(struct bregs *regs)
{
switch (regs->bl) {
case 0x80: clext_101280(regs); break;
case 0x81: clext_101281(regs); break;
case 0x82: clext_101282(regs); break;
case 0x85: clext_101285(regs); break;
case 0x9a: clext_10129a(regs); break;
case 0xa0: clext_1012a0(regs); break;
case 0xa1: clext_1012a1(regs); break;
case 0xa2: clext_1012a2(regs); break;
case 0xae: clext_1012ae(regs); break;
default: clext_1012XX(regs); break;
}
}
/****************************************************************
* init
****************************************************************/
static int
cirrus_check(void)
{
stdvga_sequ_write(0x06, 0x92);
return stdvga_sequ_read(0x06) == 0x12;
}
static u8
cirrus_get_memsize(void)
{
// get DRAM band width
u8 v = stdvga_sequ_read(0x0f);
u8 x = (v >> 3) & 0x03;
if (x == 0x03 && v & 0x80)
// 4MB
return 0x40;
return 0x04 << x;
}
int
clext_setup(void)
{
int ret = stdvga_setup();
if (ret)
return ret;
dprintf(1, "cirrus init\n");
if (! cirrus_check())
return -1;
dprintf(1, "cirrus init 2\n");
// memory setup
stdvga_sequ_write(0x0a, stdvga_sequ_read(0x0f) & 0x18);
// set vga mode
stdvga_sequ_write(0x07, 0x00);
// reset bitblt
stdvga_grdc_write(0x31, 0x04);
stdvga_grdc_write(0x31, 0x00);
if (GET_GLOBAL(HaveRunInit))
return 0;
u32 lfb_addr = 0;
int bdf = GET_GLOBAL(VgaBDF);
if (CONFIG_VGA_PCI && bdf >= 0)
lfb_addr = (pci_config_readl(bdf, PCI_BASE_ADDRESS_0)
& PCI_BASE_ADDRESS_MEM_MASK);
SET_VGA(VBE_framebuffer, lfb_addr);
u16 totalmem = cirrus_get_memsize();
SET_VGA(VBE_total_memory, totalmem * 64 * 1024);
SET_VGA(VBE_win_granularity, 16);
return 0;
}
+434
View File
@@ -0,0 +1,434 @@
// Geode GX2/LX VGA functions
//
// Copyright (C) 2009 Chris Kindt
//
// Written for Google Summer of Code 2009 for the coreboot project
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_BDA
#include "farptr.h" // SET_FARVAR
#include "geodevga.h" // geodevga_setup
#include "hw/pci.h" // pci_config_readl
#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
#include "output.h" // dprintf
#include "stdvga.h" // stdvga_crtc_write
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // VBE_total_memory
/****************************************************************
* MSR and High Mem access through VSA Virtual Register
****************************************************************/
static u64 geode_msr_read(u32 msrAddr)
{
union u64_u32_u val;
asm __volatile__ (
"movw $0x0AC1C, %%dx \n"
"movl $0xFC530007, %%eax \n"
"outl %%eax, %%dx \n"
"addb $2, %%dl \n"
"inw %%dx, %%ax \n"
: "=a" (val.lo), "=d"(val.hi)
: "c"(msrAddr)
: "cc"
);
dprintf(4, "%s(0x%08x) = 0x%08x-0x%08x\n"
, __func__, msrAddr, val.hi, val.lo);
return val.val;
}
static void geode_msr_mask(u32 msrAddr, u64 off, u64 on)
{
union u64_u32_u uand, uor;
uand.val = ~off;
uor.val = on;
dprintf(4, "%s(0x%08x, 0x%016llx, 0x%016llx)\n"
, __func__, msrAddr, off, on);
asm __volatile__ (
"push %%eax \n"
"movw $0x0AC1C, %%dx \n"
"movl $0xFC530007, %%eax \n"
"outl %%eax, %%dx \n"
"addb $2, %%dl \n"
"pop %%eax \n"
"outw %%ax, %%dx \n"
:
: "c"(msrAddr), "S" (uand.hi), "D" (uand.lo), "b" (uor.hi), "a" (uor.lo)
: "%edx","cc"
);
}
static u32 geode_mem_read(u32 addr)
{
u32 val;
asm __volatile__ (
"movw $0x0AC1C, %%dx \n"
"movl $0xFC530001, %%eax \n"
"outl %%eax, %%dx \n"
"addb $2, %%dl \n"
"inw %%dx, %%ax \n"
: "=a" (val)
: "b"(addr)
: "cc"
);
return val;
}
static void geode_mem_mask(u32 addr, u32 off, u32 or)
{
asm __volatile__ (
"movw $0x0AC1C, %%dx \n"
"movl $0xFC530001, %%eax \n"
"outl %%eax, %%dx \n"
"addb $2, %%dl \n"
"outw %%ax, %%dx \n"
:
: "b"(addr), "S" (~off), "D" (or)
: "%eax","cc"
);
}
#define VP_FP_START 0x400
static u32 GeodeFB VAR16;
static u32 GeodeDC VAR16;
static u32 GeodeVP VAR16;
static u32 geode_dc_read(int reg)
{
u32 val = geode_mem_read(GET_GLOBAL(GeodeDC) + reg);
dprintf(4, "%s(0x%08x) = 0x%08x\n"
, __func__, GET_GLOBAL(GeodeDC) + reg, val);
return val;
}
static void geode_dc_write(int reg, u32 val)
{
dprintf(4, "%s(0x%08x, 0x%08x)\n"
, __func__, GET_GLOBAL(GeodeDC) + reg, val);
geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, ~0, val);
}
static void geode_dc_mask(int reg, u32 off, u32 on)
{
dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n"
, __func__, GET_GLOBAL(GeodeDC) + reg, off, on);
geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, off, on);
}
static u32 geode_vp_read(int reg)
{
u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + reg);
dprintf(4, "%s(0x%08x) = 0x%08x\n"
, __func__, GET_GLOBAL(GeodeVP) + reg, val);
return val;
}
static void geode_vp_write(int reg, u32 val)
{
dprintf(4, "%s(0x%08x, 0x%08x)\n"
, __func__, GET_GLOBAL(GeodeVP) + reg, val);
geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, ~0, val);
}
static void geode_vp_mask(int reg, u32 off, u32 on)
{
dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n"
, __func__, GET_GLOBAL(GeodeVP) + reg, off, on);
geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, off, on);
}
static u32 geode_fp_read(int reg)
{
u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + VP_FP_START + reg);
dprintf(4, "%s(0x%08x) = 0x%08x\n"
, __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val);
return val;
}
static void geode_fp_write(int reg, u32 val)
{
dprintf(4, "%s(0x%08x, 0x%08x)\n"
, __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val);
geode_mem_mask(GET_GLOBAL(GeodeVP) + VP_FP_START + reg, ~0, val);
}
/****************************************************************
* Helper functions
****************************************************************/
static int legacyio_check(void)
{
int ret=0;
u64 val;
if (CONFIG_VGA_GEODEGX2)
val = geode_msr_read(GLIU0_P2D_BM_4);
else
val = geode_msr_read(MSR_GLIU0_BASE4);
if ((val & 0xffffffff) != 0x0A0fffe0)
ret|=1;
val = geode_msr_read(GLIU0_IOD_BM_0);
if ((val & 0xffffffff) != 0x3c0ffff0)
ret|=2;
val = geode_msr_read(GLIU0_IOD_BM_1);
if ((val & 0xffffffff) != 0x3d0ffff0)
ret|=4;
return ret;
}
static u32 framebuffer_size(void)
{
/* We use the P2D_R0 msr to read out the number of pages.
* One page has a size of 4k
*
* Bit Name Description
* 39:20 PMAX Physical Memory Address Max
* 19:0 PMIX Physical Memory Address Min
*
*/
u64 msr = geode_msr_read(GLIU0_P2D_RO);
u32 pmax = (msr >> 20) & 0x000fffff;
u32 pmin = msr & 0x000fffff;
u32 val = pmax - pmin;
val += 1;
/* The page size is 4k */
return (val << 12);
}
/****************************************************************
* Init Functions
****************************************************************/
static void geodevga_set_output_mode(void)
{
u64 msr_addr;
u64 msr;
/* set output to crt and RGB/YUV */
if (CONFIG_VGA_GEODEGX2)
msr_addr = VP_MSR_CONFIG_GX2;
else
msr_addr = VP_MSR_CONFIG_LX;
/* set output mode (RGB/YUV) */
msr = geode_msr_read(msr_addr);
msr &= ~VP_MSR_CONFIG_FMT; // mask out FMT (bits 5:3)
if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) {
msr |= VP_MSR_CONFIG_FMT_FP; // flat panel
if (CONFIG_VGA_OUTPUT_CRT_PANEL) {
msr |= VP_MSR_CONFIG_FPC; // simultaneous Flat Panel and CRT
dprintf(1, "output: simultaneous Flat Panel and CRT\n");
} else {
msr &= ~VP_MSR_CONFIG_FPC; // no simultaneous Flat Panel and CRT
dprintf(1, "ouput: flat panel\n");
}
} else {
msr |= VP_MSR_CONFIG_FMT_CRT; // CRT only
dprintf(1, "output: CRT\n");
}
geode_msr_mask(msr_addr, ~msr, msr);
}
/* Set up the dc (display controller) portion of the geodelx
* The dc provides hardware support for VGA graphics.
*/
static void dc_setup(void)
{
dprintf(2, "DC_SETUP\n");
geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK);
/* zero memory config */
geode_dc_write(DC_FB_ST_OFFSET, 0x0);
geode_dc_write(DC_CB_ST_OFFSET, 0x0);
geode_dc_write(DC_CURS_ST_OFFSET, 0x0);
geode_dc_mask(DC_DISPLAY_CFG, ~DC_CFG_MSK, DC_DISPLAY_CFG_GDEN|DC_DISPLAY_CFG_TRUP);
geode_dc_write(DC_GENERAL_CFG, DC_GENERAL_CFG_VGAE);
geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK);
}
/* Setup the vp (video processor) portion of the geodelx
* Under VGA modes the vp was handled by softvg from inside VSA2.
* Without a softvg module, access is only available through a pci bar.
* The High Mem Access virtual register is used to configure the
* pci mmio bar from 16bit friendly io space.
*/
static void vp_setup(void)
{
dprintf(2,"VP_SETUP\n");
geodevga_set_output_mode();
/* Set mmio registers
* there may be some timing issues here, the reads seem
* to slow things down enough work reliably
*/
u32 reg = geode_vp_read(VP_MISC);
dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
geode_vp_write(VP_MISC, VP_DCFG_BYP_BOTH);
reg = geode_vp_read(VP_MISC);
dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
reg = geode_vp_read(VP_DCFG);
dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
geode_vp_mask(VP_DCFG, 0, VP_DCFG_CRT_EN|VP_DCFG_HSYNC_EN|VP_DCFG_VSYNC_EN|VP_DCFG_DAC_BL_EN|VP_DCFG_CRT_SKEW);
reg = geode_vp_read(VP_DCFG);
dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
/* setup flat panel */
if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) {
u64 msr;
dprintf(1, "Setting up flat panel\n");
/* write timing register */
geode_fp_write(FP_PT1, 0x0);
geode_fp_write(FP_PT2, FP_PT2_SCRC);
/* set pad select for TFT/LVDS */
msr = VP_MSR_PADSEL_TFT_SEL_HIGH;
msr = msr << 32;
msr |= VP_MSR_PADSEL_TFT_SEL_LOW;
geode_msr_mask(VP_MSR_PADSEL, ~msr, msr);
/* turn the panel on (if it isn't already) */
reg = geode_fp_read(FP_PM);
reg |= FP_PM_P;
geode_fp_write(FP_PM, reg);
}
}
static u8 geode_crtc_01[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x14, 0x1f, 0x97, 0xb9, 0xa3,
0xff };
static u8 geode_crtc_03[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x28, 0x1f, 0x97, 0xb9, 0xa3,
0xff };
static u8 geode_crtc_04[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
0xff };
static u8 geode_crtc_05[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8e, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
0xff };
static u8 geode_crtc_06[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xc2,
0xff };
static u8 geode_crtc_07[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x28, 0x0f, 0x97, 0xb9, 0xa3,
0xff };
static u8 geode_crtc_0d[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xe3,
0xff };
static u8 geode_crtc_0e[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xe3,
0xff };
static u8 geode_crtc_0f[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x83, 0x85, 0x5d, 0x28, 0x0f, 0x65, 0xb9, 0xe3,
0xff };
static u8 geode_crtc_11[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0x0b, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
0xff };
static u8 geode_crtc_13[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9b, 0x8d, 0x8f, 0x28, 0x40, 0x98, 0xb9, 0xa3,
0xff };
int geodevga_setup(void)
{
int ret = stdvga_setup();
if (ret)
return ret;
dprintf(1,"GEODEVGA_SETUP\n");
if ((ret=legacyio_check())) {
dprintf(1,"GEODEVGA_SETUP legacyio_check=0x%x\n",ret);
}
// Updated timings from geode datasheets, table 6-53 in particular
static u8 *new_crtc[] VAR16 = {
geode_crtc_01, geode_crtc_01, geode_crtc_03, geode_crtc_03,
geode_crtc_04, geode_crtc_05, geode_crtc_06, geode_crtc_07,
0, 0, 0, 0, 0,
geode_crtc_0d, geode_crtc_0e, geode_crtc_0f, geode_crtc_0f,
geode_crtc_11, geode_crtc_11, geode_crtc_13 };
int i;
for (i=0; i<ARRAY_SIZE(new_crtc); i++) {
u8 *crtc = GET_GLOBAL(new_crtc[i]);
if (crtc)
stdvga_override_crtc(i, crtc);
}
if (GET_GLOBAL(VgaBDF) < 0)
// Device should be at 00:01.1
SET_VGA(VgaBDF, pci_to_bdf(0, 1, 1));
// setup geode struct which is used for register access
SET_VGA(GeodeFB, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_0));
SET_VGA(GeodeDC, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_2));
SET_VGA(GeodeVP, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3));
dprintf(1, "fb addr: 0x%08x\n", GET_GLOBAL(GeodeFB));
dprintf(1, "dc addr: 0x%08x\n", GET_GLOBAL(GeodeDC));
dprintf(1, "vp addr: 0x%08x\n", GET_GLOBAL(GeodeVP));
/* setup framebuffer */
geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK);
/* read fb-bar from pci, then point dc to the fb base */
u32 fb = GET_GLOBAL(GeodeFB);
if (geode_dc_read(DC_GLIU0_MEM_OFFSET) != fb)
geode_dc_write(DC_GLIU0_MEM_OFFSET, fb);
geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK);
u32 fb_size = framebuffer_size(); // in byte
dprintf(1, "%d KB of video memory at 0x%08x\n", fb_size / 1024, fb);
/* update VBE variables */
SET_VGA(VBE_framebuffer, fb);
SET_VGA(VBE_total_memory, fb_size / 1024 / 64); // number of 64K blocks
vp_setup();
dc_setup();
return 0;
}
+89
View File
@@ -0,0 +1,89 @@
// Geode GX2/LX VGA functions
//
// Copyright (C) 2009 Chris Kindt
//
// Written for Google Summer of Code 2009 for the coreboot project
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#ifndef GEODEVGA_H
#define GEODEVGA_H
#define VRC_INDEX 0xAC1C // Index register
#define VRC_DATA 0xAC1E // Data register
#define VR_UNLOCK 0xFC53 // Virtual register unlock code
// Graphics-specific registers:
#define OEM_BAR0 0x50
#define OEM_BAR1 0x54
#define OEM_BAR2 0x58
#define OEM_BAR3 0x5C
#define DC_LOCK_LOCK 0x00000000
#define DC_LOCK_UNLOCK 0x00004758
/* LX MSRs */
#define MSR_GLIU0 (1 << 28)
#define MSR_GLIU0_BASE4 (MSR_GLIU0 + 0x23) /* LX */
#define GLIU0_P2D_BM_4 (MSR_GLIU0 + 0x24) /* GX2 */
#define GLIU0_P2D_RO (MSR_GLIU0 + 0x29)
#define GLIU0_IOD_BM_0 (MSR_GLIU0 + 0xE0)
#define GLIU0_IOD_BM_1 (MSR_GLIU0 + 0xE1)
#define DC_SPARE 0x80000011
#define VP_MSR_CONFIG_GX2 0xc0002001 /* GX2 */
#define VP_MSR_CONFIG_LX 0x48002001 /* LX */
#define VP_MSR_PADSEL 0x48002011
#define VP_MSR_PADSEL_TFT_SEL_LOW 0xDFFFFFFF
#define VP_MSR_PADSEL_TFT_SEL_HIGH 0x0000003F
/* VP_MSR_CONFIG bits */
#define VP_MSR_CONFIG_FMT_CRT (0)
#define VP_MSR_CONFIG_FMT_FP (1 << 3)
#define VP_MSR_CONFIG_FPC (1 << 15)
#define VP_MSR_CONFIG_FMT ((1 << 3) | (1 << 4) | (1 << 5))
/* DC REG OFFSET */
#define DC_UNLOCK 0x0
#define DC_GENERAL_CFG 0x4
#define DC_DISPLAY_CFG 0x8
#define DC_FB_ST_OFFSET 0x10
#define DC_CB_ST_OFFSET 0x14
#define DC_CURS_ST_OFFSET 0x18
#define DC_GLIU0_MEM_OFFSET 0x84
/* VP REG OFFSET */
#define VP_VCFG 0x0
#define VP_DCFG 0x8
#define VP_MISC 0x50
/* FP REG OFFSET */
#define FP_PT1 0x00
#define FP_PT2 0x08
#define FP_PM 0x10
/* DC bits */
#define DC_GENERAL_CFG_VGAE (1 << 7)
#define DC_DISPLAY_CFG_GDEN (1 << 3)
#define DC_DISPLAY_CFG_TRUP (1 << 6)
/* VP bits */
#define VP_DCFG_CRT_EN (1 << 0)
#define VP_DCFG_HSYNC_EN (1 << 1)
#define VP_DCFG_VSYNC_EN (1 << 2)
#define VP_DCFG_DAC_BL_EN (1 << 3)
#define VP_DCFG_CRT_SKEW (1 << 16)
#define VP_DCFG_BYP_BOTH (1 << 0)
/* FP bits */
#define FP_PM_P (1 << 24) /* panel power ctl */
#define FP_PT2_SCRC (1 << 27) /* panel shift clock retrace activity ctl */
/* Mask */
#define DC_CFG_MSK 0xf000a6
int geodevga_setup();
#endif
+169
View File
@@ -0,0 +1,169 @@
// Simple framebuffer vgabios for use with qemu ramfb device
//
// Copyright (C) 2019 Gerd Hoffmann <kraxel@redhat.com>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_BDA
#include "output.h" // dprintf
#include "string.h" // memset16_far
#include "vgautil.h" // VBE_total_memory
#include "std/pmm.h" // struct pmmheader
#include "byteorder.h"
#include "fw/paravirt.h"
/* ---------------------------------------------------------------------- */
/* minimal qemu fc_cfg support bits, requires dma support */
#define QEMU_CFG_FILE_DIR 0x19
struct QemuCfgFile {
u32 size; /* file size */
u16 select; /* write this to 0x510 to read it */
u16 reserved;
char name[56];
};
static void
qemu_cfg_dma_transfer(void *address, u32 length, u32 control)
{
QemuCfgDmaAccess access;
if (length == 0) {
return;
}
access.address = cpu_to_be64((u64)(u32)address);
access.length = cpu_to_be32(length);
access.control = cpu_to_be32(control);
barrier();
outl(cpu_to_be32((u32)&access), PORT_QEMU_CFG_DMA_ADDR_LOW);
while(be32_to_cpu(access.control) & ~QEMU_CFG_DMA_CTL_ERROR)
/* wait */;
}
static void
qemu_cfg_read(void *buf, int len)
{
qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_READ);
}
static void
qemu_cfg_read_entry(void *buf, int e, int len)
{
u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
| QEMU_CFG_DMA_CTL_READ;
qemu_cfg_dma_transfer(buf, len, control);
}
static void
qemu_cfg_write_entry(void *buf, int e, int len)
{
u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
| QEMU_CFG_DMA_CTL_WRITE;
qemu_cfg_dma_transfer(buf, len, control);
}
static int
qemu_cfg_find_file(const char *filename)
{
u32 count, e, select;
qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
count = be32_to_cpu(count);
for (select = 0, e = 0; e < count; e++) {
struct QemuCfgFile qfile;
qemu_cfg_read(&qfile, sizeof(qfile));
if (memcmp_far(GET_SEG(SS), qfile.name,
GET_SEG(CS), filename, 10) == 0)
select = be16_to_cpu(qfile.select);
}
return select;
}
/* ---------------------------------------------------------------------- */
#define FRAMEBUFFER_WIDTH 1024
#define FRAMEBUFFER_HEIGHT 768
#define FRAMEBUFFER_BPP 4
#define FRAMEBUFFER_STRIDE (FRAMEBUFFER_BPP * FRAMEBUFFER_WIDTH)
#define FRAMEBUFFER_SIZE (FRAMEBUFFER_STRIDE * FRAMEBUFFER_HEIGHT)
struct QemuRAMFBCfg {
u64 addr;
u32 fourcc;
u32 flags;
u32 width;
u32 height;
u32 stride;
};
#define fourcc_code(a, b, c, d) ((u32)(a) | ((u32)(b) << 8) | \
((u32)(c) << 16) | ((u32)(d) << 24))
#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
static u32
allocate_framebuffer(void)
{
u32 res = allocate_pmm(FRAMEBUFFER_SIZE, 1, 1);
if (!res)
return 0;
dprintf(1, "ramfb: framebuffer allocated at %x\n", res);
return res;
}
int
ramfb_setup(void)
{
dprintf(1, "ramfb: init\n");
if (GET_GLOBAL(HaveRunInit))
return 0;
u32 select = qemu_cfg_find_file("etc/ramfb");
if (select == 0) {
dprintf(1, "ramfb: fw_cfg (etc/ramfb) file not found\n");
return -1;
}
dprintf(1, "ramfb: fw_cfg (etc/ramfb) file at slot 0x%x\n", select);
u32 fb = allocate_framebuffer();
if (!fb) {
dprintf(1, "ramfb: allocating framebuffer failed\n");
return -1;
}
u64 addr = fb;
u8 bpp = FRAMEBUFFER_BPP * 8;
u32 xlines = FRAMEBUFFER_WIDTH;
u32 ylines = FRAMEBUFFER_HEIGHT;
u32 linelength = FRAMEBUFFER_STRIDE;
dprintf(1, "Found FB @ %llx %dx%d with %d bpp (%d stride)\n"
, addr, xlines, ylines, bpp, linelength);
if (!addr || addr > 0xffffffff
|| (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32)) {
dprintf(1, "Unable to use FB\n");
return -1;
}
cbvga_setup_modes(addr, bpp, xlines, ylines, linelength);
struct QemuRAMFBCfg cfg = {
.addr = cpu_to_be64(fb),
.fourcc = cpu_to_be32(DRM_FORMAT_XRGB8888),
.flags = cpu_to_be32(0),
.width = cpu_to_be32(FRAMEBUFFER_WIDTH),
.height = cpu_to_be32(FRAMEBUFFER_HEIGHT),
.stride = cpu_to_be32(FRAMEBUFFER_STRIDE),
};
qemu_cfg_write_entry(&cfg, select, sizeof(cfg));
return 0;
}
+567
View File
@@ -0,0 +1,567 @@
// Standard VGA driver code
//
// Copyright (C) 2009-2024 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 "biosvar.h" // GET_GLOBAL
#include "farptr.h" // SET_FARVAR
#include "stdvga.h" // stdvga_setup
#include "string.h" // memset_far
#include "vgabios.h" // struct vgamode_s
#include "x86.h" // outb
/****************************************************************
* Attribute control
****************************************************************/
// Emulate CGA background setting via VGA palette index registers
void
stdvga_set_cga_background_color(u8 color)
{
// Set the background color (via palette index 0)
u8 v1 = color & 0x0f;
if (v1 & 0x08)
v1 += 0x08;
stdvga_attr_write(0x00, v1);
// Dim/brighten foreground (see pal_cga[] in stdvgamodes.c)
int i;
for (i = 1; i < 4; i++)
stdvga_attr_mask(i, 0x10, color & 0x10);
}
// Emulate CGA palette setting by altering VGA palette index registers
void
stdvga_set_cga_palette(u8 palid)
{
// Switch foreground colors (see pal_cga[] in stdvgamodes.c)
int i;
for (i = 1; i < 4; i++)
stdvga_attr_mask(i, 0x01, palid & 0x01);
}
// Set the VGA palette index register for the "overscan" area
void
stdvga_set_overscan_border_color(u8 color)
{
stdvga_attr_write(0x11, color);
}
// Get the VGA palette index register for the "overscan" area
u8
stdvga_get_overscan_border_color(void)
{
return stdvga_attr_read(0x11);
}
// Set the VGA palette index registers
void
stdvga_set_all_palette_reg(u16 seg, u8 *data_far)
{
// Set palette indexes (offset into DAC colors)
int i;
for (i = 0; i < 0x10; i++) {
stdvga_attr_write(i, GET_FARVAR(seg, *data_far));
data_far++;
}
// Set "overscan" palette index (offset into DAC colors)
stdvga_attr_write(0x11, GET_FARVAR(seg, *data_far));
}
// Get the VGA palette index registers
void
stdvga_get_all_palette_reg(u16 seg, u8 *data_far)
{
int i;
for (i = 0; i < 0x10; i++) {
SET_FARVAR(seg, *data_far, stdvga_attr_read(i));
data_far++;
}
SET_FARVAR(seg, *data_far, stdvga_attr_read(0x11));
}
// Set blinking mode (when enabled, palette index bit 0x08 indicates blinking)
void
stdvga_set_palette_blinking(u8 enable_blink)
{
stdvga_attr_mask(0x10, 0x08, (enable_blink & 0x01) << 3);
}
// Select 4-bit or 6-bit palette indexes (for "page" switching of colors)
void
stdvga_set_palette_pagesize(u8 pal_pagesize)
{
stdvga_attr_mask(0x10, 0x80, pal_pagesize << 7);
}
// Set palette index offset (enables color switching via "pages")
void
stdvga_set_palette_page(u8 pal_page)
{
// Check if using 4-bit or 6-bit "palette index pages"
u8 val = stdvga_attr_read(0x10);
if (!(val & 0x80))
pal_page <<= 2;
// select page
pal_page &= 0x0f;
stdvga_attr_write(0x14, pal_page);
}
// Report current palette index pagesize and current page
void
stdvga_get_palette_page(u8 *pal_pagesize, u8 *pal_page)
{
u8 val1 = stdvga_attr_read(0x10) >> 7;
u8 val2 = stdvga_attr_read(0x14) & 0x0f;
if (!(val1 & 0x01))
val2 >>= 2;
*pal_pagesize = val1;
*pal_page = val2;
}
/****************************************************************
* DAC control
****************************************************************/
// Store dac colors into memory in 3-byte rgb format
void
stdvga_dac_read_many(u16 seg, u8 *data_far, u8 start, int count)
{
while (count) {
struct vbe_palette_entry rgb = stdvga_dac_read(start);
SET_FARVAR(seg, *data_far, rgb.red);
data_far++;
SET_FARVAR(seg, *data_far, rgb.green);
data_far++;
SET_FARVAR(seg, *data_far, rgb.blue);
data_far++;
start++;
count--;
}
}
// Load dac colors from memory in 3-byte rgb format
void
stdvga_dac_write_many(u16 seg, u8 *data_far, u8 start, int count)
{
while (count) {
u8 r = GET_FARVAR(seg, *data_far);
data_far++;
u8 g = GET_FARVAR(seg, *data_far);
data_far++;
u8 b = GET_FARVAR(seg, *data_far);
data_far++;
struct vbe_palette_entry rgb = { .red=r, .green=g, .blue=b };
stdvga_dac_write(start, rgb);
start++;
count--;
}
}
// Convert all loaded colors to shades of gray
void
stdvga_perform_gray_scale_summing(u16 start, u16 count)
{
stdvga_attrindex_write(0x00);
int i;
for (i = start; i < start+count; i++) {
struct vbe_palette_entry rgb = stdvga_dac_read(i);
// intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
u16 intensity = ((77 * rgb.red + 151 * rgb.green
+ 28 * rgb.blue) + 0x80) >> 8;
if (intensity > 0x3f)
intensity = 0x3f;
rgb.red = rgb.green = rgb.blue = intensity;
stdvga_dac_write(i, rgb);
}
stdvga_attrindex_write(0x20);
}
/****************************************************************
* Memory control
****************************************************************/
// Enable reads and writes to the given "plane" when in planar4 mode.
void
stdvga_planar4_plane(int plane)
{
if (plane < 0) {
// Return to default mode (read plane0, write all planes)
stdvga_sequ_write(0x02, 0x0f);
stdvga_grdc_write(0x04, 0);
} else {
stdvga_sequ_write(0x02, 1<<plane);
stdvga_grdc_write(0x04, plane);
}
}
/****************************************************************
* Font loading
****************************************************************/
// Set the video memory location of the start of character fonts
void
stdvga_set_font_location(u8 spec)
{
stdvga_sequ_write(0x03, spec);
}
static void
get_font_access(void)
{
stdvga_sequ_write(0x00, 0x01);
stdvga_sequ_write(0x02, 0x04);
stdvga_sequ_write(0x04, 0x07);
stdvga_sequ_write(0x00, 0x03);
stdvga_grdc_write(0x04, 0x02);
stdvga_grdc_write(0x05, 0x00);
stdvga_grdc_write(0x06, 0x04);
}
static void
release_font_access(void)
{
stdvga_sequ_write(0x00, 0x01);
stdvga_sequ_write(0x02, 0x03);
stdvga_sequ_write(0x04, 0x03);
stdvga_sequ_write(0x00, 0x03);
u16 v = (stdvga_misc_read() & 0x01) ? 0x0e : 0x0a;
stdvga_grdc_write(0x06, v);
stdvga_grdc_write(0x04, 0x00);
stdvga_grdc_write(0x05, 0x10);
}
void
stdvga_load_font(u16 seg, void *src_far, u16 count
, u16 start, u8 destflags, u8 fontsize)
{
get_font_access();
u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11);
void *dest_far = (void*)(blockaddr + start*32);
u16 i;
for (i = 0; i < count; i++)
memcpy_far(SEG_GRAPH, dest_far + i*32
, seg, src_far + i*fontsize, fontsize);
release_font_access();
}
/****************************************************************
* CRTC registers
****************************************************************/
// Return the IO port used to access the CRTC register
u16
stdvga_get_crtc(void)
{
if (stdvga_misc_read() & 1)
return VGAREG_VGA_CRTC_ADDRESS;
return VGAREG_MDA_CRTC_ADDRESS;
}
// Ratio between system visible framebuffer ram and the actual videoram used.
int
stdvga_vram_ratio(struct vgamode_s *vmode_g)
{
switch (GET_GLOBAL(vmode_g->memmodel)) {
case MM_TEXT:
return 2;
case MM_CGA:
return 4 / GET_GLOBAL(vmode_g->depth);
case MM_PLANAR:
return 4;
default:
return 1;
}
}
// Set cursor shape (when in text mode)
void
stdvga_set_cursor_shape(u16 cursor_type)
{
u16 crtc_addr = stdvga_get_crtc();
stdvga_crtc_write(crtc_addr, 0x0a, cursor_type >> 8);
stdvga_crtc_write(crtc_addr, 0x0b, cursor_type);
}
// Set the position of the text cursor (as offset into system framebuffer)
void
stdvga_set_cursor_pos(int address)
{
u16 crtc_addr = stdvga_get_crtc();
address /= 2; // Assume we're in text mode.
stdvga_crtc_write(crtc_addr, 0x0e, address >> 8);
stdvga_crtc_write(crtc_addr, 0x0f, address);
}
// Set the character height (when in text mode)
void
stdvga_set_character_height(u8 lines)
{
stdvga_crtc_mask(stdvga_get_crtc(), 0x09, 0x1f, lines - 1);
}
// Get vertical screen size (number of horizontal lines in the display)
u16
stdvga_get_vertical_size(void)
{
u16 crtc_addr = stdvga_get_crtc();
u16 vde = stdvga_crtc_read(crtc_addr, 0x12);
u8 ovl = stdvga_crtc_read(crtc_addr, 0x07);
vde += ((ovl & 0x02) << 7) + ((ovl & 0x40) << 3);
return vde + 1;
}
// Set vertical screen size (number of horizontal lines in the display)
void
stdvga_set_vertical_size(int lines)
{
u16 crtc_addr = stdvga_get_crtc();
u16 vde = lines - 1;
stdvga_crtc_write(crtc_addr, 0x12, vde);
u8 ovl = ((vde >> 7) & 0x02) + ((vde >> 3) & 0x40);
stdvga_crtc_mask(crtc_addr, 0x07, 0x42, ovl);
}
// Get offset into framebuffer accessible from real-mode 64K segment
int
stdvga_get_window(struct vgamode_s *curmode_g, int window)
{
return -1;
}
// Set offset into framebuffer that is accessible from real-mode 64K
// segment (in units of VBE_win_granularity windows)
int
stdvga_set_window(struct vgamode_s *curmode_g, int window, int val)
{
// Stdvga does not support changing window offset
return -1;
}
// Minimum framebuffer bytes between each vertical line for given mode
int
stdvga_minimum_linelength(struct vgamode_s *vmode_g)
{
return DIV_ROUND_UP(GET_GLOBAL(vmode_g->width) * vga_bpp(vmode_g), 8);
}
// Return number of framebuffer bytes between start of each vertical line
int
stdvga_get_linelength(struct vgamode_s *curmode_g)
{
u8 val = stdvga_crtc_read(stdvga_get_crtc(), 0x13);
return val * 8 / stdvga_vram_ratio(curmode_g);
}
// Set number of framebuffer bytes between start of each vertical line
int
stdvga_set_linelength(struct vgamode_s *curmode_g, int val)
{
val = DIV_ROUND_UP(val * stdvga_vram_ratio(curmode_g), 8);
stdvga_crtc_write(stdvga_get_crtc(), 0x13, val);
return 0;
}
// Return framebuffer offset of first byte of displayed content
int
stdvga_get_displaystart(struct vgamode_s *curmode_g)
{
u16 crtc_addr = stdvga_get_crtc();
int addr = (stdvga_crtc_read(crtc_addr, 0x0c) << 8
| stdvga_crtc_read(crtc_addr, 0x0d));
return addr * 4 / stdvga_vram_ratio(curmode_g);
}
// Set framebuffer offset of first byte of displayed content
int
stdvga_set_displaystart(struct vgamode_s *curmode_g, int val)
{
u16 crtc_addr = stdvga_get_crtc();
val = val * stdvga_vram_ratio(curmode_g) / 4;
stdvga_crtc_write(crtc_addr, 0x0c, val >> 8);
stdvga_crtc_write(crtc_addr, 0x0d, val);
return 0;
}
// Report if using 8bit per rgb (24bit total) or 6bit per rgb (18bit total)
int
stdvga_get_dacformat(struct vgamode_s *curmode_g)
{
return -1;
}
// Set 8bit per rgb (24bit total) or 6bit per rgb (18bit total)
int
stdvga_set_dacformat(struct vgamode_s *curmode_g, int val)
{
// Stdvga only supports 6bits for each color channel
return -1;
}
/****************************************************************
* Save/Restore state
****************************************************************/
struct saveVideoHardware {
u8 sequ_index;
u8 crtc_index;
u8 grdc_index;
u8 actl_index;
u8 feature;
u8 sequ_regs[4];
u8 sequ0;
u8 crtc_regs[25];
u8 actl_regs[20];
u8 grdc_regs[9];
u16 crtc_addr;
u8 plane_latch[4];
} PACKED;
static void
stdvga_save_hw_state(u16 seg, struct saveVideoHardware *info)
{
u16 crtc_addr = stdvga_get_crtc();
SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
SET_FARVAR(seg, info->actl_index, stdvga_attrindex_read());
SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
int i;
for (i=0; i<4; i++)
SET_FARVAR(seg, info->sequ_regs[i], stdvga_sequ_read(i+1));
SET_FARVAR(seg, info->sequ0, stdvga_sequ_read(0));
for (i=0; i<25; i++)
SET_FARVAR(seg, info->crtc_regs[i], stdvga_crtc_read(crtc_addr, i));
for (i=0; i<20; i++)
SET_FARVAR(seg, info->actl_regs[i], stdvga_attr_read(i));
for (i=0; i<9; i++)
SET_FARVAR(seg, info->grdc_regs[i], stdvga_grdc_read(i));
SET_FARVAR(seg, info->crtc_addr, crtc_addr);
/* XXX: read plane latches */
for (i=0; i<4; i++)
SET_FARVAR(seg, info->plane_latch[i], 0);
}
static void
stdvga_restore_hw_state(u16 seg, struct saveVideoHardware *info)
{
int i;
for (i=0; i<4; i++)
stdvga_sequ_write(i+1, GET_FARVAR(seg, info->sequ_regs[i]));
stdvga_sequ_write(0x00, GET_FARVAR(seg, info->sequ0));
// Disable CRTC write protection
u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
stdvga_crtc_write(crtc_addr, 0x11, 0x00);
// Set CRTC regs
for (i=0; i<25; i++)
if (i != 0x11)
stdvga_crtc_write(crtc_addr, i, GET_FARVAR(seg, info->crtc_regs[i]));
// select crtc base address
stdvga_misc_mask(0x01, crtc_addr == VGAREG_VGA_CRTC_ADDRESS ? 0x01 : 0x00);
// enable write protection if needed
stdvga_crtc_write(crtc_addr, 0x11, GET_FARVAR(seg, info->crtc_regs[0x11]));
// Set Attribute Ctl
for (i=0; i<20; i++)
stdvga_attr_write(i, GET_FARVAR(seg, info->actl_regs[i]));
stdvga_attrindex_write(GET_FARVAR(seg, info->actl_index));
for (i=0; i<9; i++)
stdvga_grdc_write(i, GET_FARVAR(seg, info->grdc_regs[i]));
outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
}
struct saveDACcolors {
u8 rwmode;
u8 peladdr;
u8 pelmask;
u8 dac[768];
u8 color_select;
} PACKED;
static void
stdvga_save_dac_state(u16 seg, struct saveDACcolors *info)
{
/* XXX: check this */
SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
SET_FARVAR(seg, info->pelmask, stdvga_pelmask_read());
stdvga_dac_read_many(seg, info->dac, 0, 256);
SET_FARVAR(seg, info->color_select, 0);
}
static void
stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info)
{
stdvga_pelmask_write(GET_FARVAR(seg, info->pelmask));
stdvga_dac_write_many(seg, info->dac, 0, 256);
outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
}
int
stdvga_save_restore(int cmd, u16 seg, void *data)
{
void *pos = data;
if (cmd & SR_HARDWARE) {
if (cmd & SR_SAVE)
stdvga_save_hw_state(seg, pos);
if (cmd & SR_RESTORE)
stdvga_restore_hw_state(seg, pos);
pos += sizeof(struct saveVideoHardware);
}
pos += bda_save_restore(cmd, seg, pos);
if (cmd & SR_DAC) {
if (cmd & SR_SAVE)
stdvga_save_dac_state(seg, pos);
if (cmd & SR_RESTORE)
stdvga_restore_dac_state(seg, pos);
pos += sizeof(struct saveDACcolors);
}
return pos - data;
}
/****************************************************************
* Misc
****************************************************************/
// Enable/disable system access to the video memory
void
stdvga_enable_video_addressing(u8 disable)
{
u8 v = (disable & 1) ? 0x00 : 0x02;
stdvga_misc_mask(0x02, v);
}
int
stdvga_setup(void)
{
// switch to color mode and enable CPU access 480 lines
stdvga_misc_write(0xc3);
// more than 64k 3C4/04
stdvga_sequ_write(0x04, 0x02);
return 0;
}
+110
View File
@@ -0,0 +1,110 @@
#ifndef __STDVGA_H
#define __STDVGA_H
#include "types.h" // u8
#include "std/vbe.h" // struct vbe_palette_entry
// VGA registers
#define VGAREG_ACTL_ADDRESS 0x3c0
#define VGAREG_ACTL_WRITE_DATA 0x3c0
#define VGAREG_ACTL_READ_DATA 0x3c1
#define VGAREG_INPUT_STATUS 0x3c2
#define VGAREG_WRITE_MISC_OUTPUT 0x3c2
#define VGAREG_VIDEO_ENABLE 0x3c3
#define VGAREG_SEQU_ADDRESS 0x3c4
#define VGAREG_SEQU_DATA 0x3c5
#define VGAREG_PEL_MASK 0x3c6
#define VGAREG_DAC_STATE 0x3c7
#define VGAREG_DAC_READ_ADDRESS 0x3c7
#define VGAREG_DAC_WRITE_ADDRESS 0x3c8
#define VGAREG_DAC_DATA 0x3c9
#define VGAREG_READ_FEATURE_CTL 0x3ca
#define VGAREG_READ_MISC_OUTPUT 0x3cc
#define VGAREG_GRDC_ADDRESS 0x3ce
#define VGAREG_GRDC_DATA 0x3cf
#define VGAREG_MDA_CRTC_ADDRESS 0x3b4
#define VGAREG_MDA_CRTC_DATA 0x3b5
#define VGAREG_VGA_CRTC_ADDRESS 0x3d4
#define VGAREG_VGA_CRTC_DATA 0x3d5
#define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba
#define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da
#define VGAREG_ACTL_RESET 0x3da
#define VGAREG_MDA_MODECTL 0x3b8
#define VGAREG_CGA_MODECTL 0x3d8
#define VGAREG_CGA_PALETTE 0x3d9
/* Video memory */
#define SEG_GRAPH 0xA000
#define SEG_CTEXT 0xB800
#define SEG_MTEXT 0xB000
// stdvga.c
void stdvga_set_cga_background_color(u8 color);
void stdvga_set_cga_palette(u8 palid);
void stdvga_set_overscan_border_color(u8 color);
u8 stdvga_get_overscan_border_color(void);
void stdvga_set_all_palette_reg(u16 seg, u8 *data_far);
void stdvga_get_all_palette_reg(u16 seg, u8 *data_far);
void stdvga_set_palette_blinking(u8 enable_blink);
void stdvga_set_palette_pagesize(u8 pal_pagesize);
void stdvga_set_palette_page(u8 pal_page);
void stdvga_get_palette_page(u8 *pal_pagesize, u8 *pal_page);
void stdvga_dac_read_many(u16 seg, u8 *data_far, u8 start, int count);
void stdvga_dac_write_many(u16 seg, u8 *data_far, u8 start, int count);
void stdvga_perform_gray_scale_summing(u16 start, u16 count);
void stdvga_planar4_plane(int plane);
void stdvga_set_font_location(u8 spec);
void stdvga_load_font(u16 seg, void *src_far, u16 count
, u16 start, u8 destflags, u8 fontsize);
u16 stdvga_get_crtc(void);
struct vgamode_s;
int stdvga_vram_ratio(struct vgamode_s *vmode_g);
void stdvga_set_cursor_shape(u16 cursor_type);
void stdvga_set_cursor_pos(int address);
void stdvga_set_character_height(u8 lines);
u16 stdvga_get_vertical_size(void);
void stdvga_set_vertical_size(int lines);
int stdvga_get_window(struct vgamode_s *curmode_g, int window);
int stdvga_set_window(struct vgamode_s *curmode_g, int window, int val);
int stdvga_minimum_linelength(struct vgamode_s *vmode_g);
int stdvga_get_linelength(struct vgamode_s *curmode_g);
int stdvga_set_linelength(struct vgamode_s *curmode_g, int val);
int stdvga_get_displaystart(struct vgamode_s *curmode_g);
int stdvga_set_displaystart(struct vgamode_s *curmode_g, int val);
int stdvga_get_dacformat(struct vgamode_s *curmode_g);
int stdvga_set_dacformat(struct vgamode_s *curmode_g, int val);
int stdvga_save_restore(int cmd, u16 seg, void *data);
void stdvga_enable_video_addressing(u8 disable);
int stdvga_setup(void);
// stdvgaio.c
u8 stdvga_pelmask_read(void);
void stdvga_pelmask_write(u8 val);
u8 stdvga_misc_read(void);
void stdvga_misc_write(u8 value);
void stdvga_misc_mask(u8 off, u8 on);
u8 stdvga_sequ_read(u8 index);
void stdvga_sequ_write(u8 index, u8 value);
void stdvga_sequ_mask(u8 index, u8 off, u8 on);
u8 stdvga_grdc_read(u8 index);
void stdvga_grdc_write(u8 index, u8 value);
void stdvga_grdc_mask(u8 index, u8 off, u8 on);
u8 stdvga_crtc_read(u16 crtc_addr, u8 index);
void stdvga_crtc_write(u16 crtc_addr, u8 index, u8 value);
void stdvga_crtc_mask(u16 crtc_addr, u8 index, u8 off, u8 on);
u8 stdvga_attr_read(u8 index);
void stdvga_attr_write(u8 index, u8 value);
void stdvga_attr_mask(u8 index, u8 off, u8 on);
u8 stdvga_attrindex_read(void);
void stdvga_attrindex_write(u8 value);
struct vbe_palette_entry stdvga_dac_read(u8 color);
void stdvga_dac_write(u8 color, struct vbe_palette_entry rgb);
#endif // stdvga.h
+174
View File
@@ -0,0 +1,174 @@
// Standard VGA IO port access
//
// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "farptr.h" // GET_FARVAR
#include "stdvga.h" // VGAREG_PEL_MASK
#include "x86.h" // inb
u8
stdvga_pelmask_read(void)
{
return inb(VGAREG_PEL_MASK);
}
void
stdvga_pelmask_write(u8 value)
{
outb(value, VGAREG_PEL_MASK);
}
u8
stdvga_misc_read(void)
{
return inb(VGAREG_READ_MISC_OUTPUT);
}
void
stdvga_misc_write(u8 value)
{
outb(value, VGAREG_WRITE_MISC_OUTPUT);
}
void
stdvga_misc_mask(u8 off, u8 on)
{
stdvga_misc_write((stdvga_misc_read() & ~off) | on);
}
u8
stdvga_sequ_read(u8 index)
{
outb(index, VGAREG_SEQU_ADDRESS);
return inb(VGAREG_SEQU_DATA);
}
void
stdvga_sequ_write(u8 index, u8 value)
{
outw((value<<8) | index, VGAREG_SEQU_ADDRESS);
}
void
stdvga_sequ_mask(u8 index, u8 off, u8 on)
{
outb(index, VGAREG_SEQU_ADDRESS);
u8 v = inb(VGAREG_SEQU_DATA);
outb((v & ~off) | on, VGAREG_SEQU_DATA);
}
u8
stdvga_grdc_read(u8 index)
{
outb(index, VGAREG_GRDC_ADDRESS);
return inb(VGAREG_GRDC_DATA);
}
void
stdvga_grdc_write(u8 index, u8 value)
{
outw((value<<8) | index, VGAREG_GRDC_ADDRESS);
}
void
stdvga_grdc_mask(u8 index, u8 off, u8 on)
{
outb(index, VGAREG_GRDC_ADDRESS);
u8 v = inb(VGAREG_GRDC_DATA);
outb((v & ~off) | on, VGAREG_GRDC_DATA);
}
u8
stdvga_crtc_read(u16 crtc_addr, u8 index)
{
outb(index, crtc_addr);
return inb(crtc_addr + 1);
}
void
stdvga_crtc_write(u16 crtc_addr, u8 index, u8 value)
{
outw((value<<8) | index, crtc_addr);
}
void
stdvga_crtc_mask(u16 crtc_addr, u8 index, u8 off, u8 on)
{
outb(index, crtc_addr);
u8 v = inb(crtc_addr + 1);
outb((v & ~off) | on, crtc_addr + 1);
}
u8
stdvga_attr_read(u8 index)
{
inb(VGAREG_ACTL_RESET);
u8 orig = inb(VGAREG_ACTL_ADDRESS);
outb(index, VGAREG_ACTL_ADDRESS);
u8 v = inb(VGAREG_ACTL_READ_DATA);
inb(VGAREG_ACTL_RESET);
outb(orig, VGAREG_ACTL_ADDRESS);
return v;
}
void
stdvga_attr_write(u8 index, u8 value)
{
inb(VGAREG_ACTL_RESET);
u8 orig = inb(VGAREG_ACTL_ADDRESS);
outb(index, VGAREG_ACTL_ADDRESS);
outb(value, VGAREG_ACTL_WRITE_DATA);
outb(orig, VGAREG_ACTL_ADDRESS);
}
void
stdvga_attr_mask(u8 index, u8 off, u8 on)
{
inb(VGAREG_ACTL_RESET);
u8 orig = inb(VGAREG_ACTL_ADDRESS);
outb(index, VGAREG_ACTL_ADDRESS);
u8 v = inb(VGAREG_ACTL_READ_DATA);
outb((v & ~off) | on, VGAREG_ACTL_WRITE_DATA);
outb(orig, VGAREG_ACTL_ADDRESS);
}
u8
stdvga_attrindex_read(void)
{
inb(VGAREG_ACTL_RESET);
return inb(VGAREG_ACTL_ADDRESS);
}
void
stdvga_attrindex_write(u8 value)
{
inb(VGAREG_ACTL_RESET);
outb(value, VGAREG_ACTL_ADDRESS);
}
struct vbe_palette_entry
stdvga_dac_read(u8 color)
{
outb(color, VGAREG_DAC_READ_ADDRESS);
u8 r = inb(VGAREG_DAC_DATA);
u8 g = inb(VGAREG_DAC_DATA);
u8 b = inb(VGAREG_DAC_DATA);
return (struct vbe_palette_entry){ .red=r, .green=g, .blue=b };
}
void
stdvga_dac_write(u8 color, struct vbe_palette_entry rgb)
{
outb(color, VGAREG_DAC_WRITE_ADDRESS);
outb(rgb.red, VGAREG_DAC_DATA);
outb(rgb.green, VGAREG_DAC_DATA);
outb(rgb.blue, VGAREG_DAC_DATA);
}
+539
View File
@@ -0,0 +1,539 @@
// Standard VGA mode information.
//
// 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 "biosvar.h" // GET_GLOBAL
#include "output.h" // warn_internalerror
#include "std/vga.h" // struct video_param_s
#include "stdvga.h" // stdvga_find_mode
#include "string.h" // memcpy_far
#include "vgabios.h" // SET_VGA
#include "vgautil.h" // vgafont16
/****************************************************************
* Default color palettes (stored in DAC registers)
****************************************************************/
// 4 grey palette used for MDA card compatibility
static u8 pal_mda[] VAR16 = {
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f
};
// 16 colors used for CGA mode compatibility
static u8 pal_cga[] VAR16 = {
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
};
// 64 colors used for EGA mode compatibility
static u8 pal_ega[] VAR16 = {
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f,
0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a,
0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a,
0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f,
0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f,
0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a,
0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a,
0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f,
0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f,
0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a,
0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
};
// Default 256 colors used in VGA "packed" mode
static u8 pal_vga[] VAR16 = {
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b,
0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18,
0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28,
0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f,
0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f,
0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10,
0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00,
0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00,
0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f,
0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f,
0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f,
0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27,
0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f,
0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f,
0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37,
0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f,
0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f,
0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31,
0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d,
0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d,
0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a,
0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f,
0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c,
0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07,
0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00,
0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00,
0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15,
0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c,
0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c,
0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11,
0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e,
0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e,
0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18,
0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c,
0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c,
0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16,
0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14,
0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14,
0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a,
0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c,
0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10,
0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04,
0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00,
0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00,
0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c,
0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10,
0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10,
0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a,
0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08,
0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08,
0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e,
0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10,
0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10,
0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c,
0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b,
0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b,
0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f,
0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00
};
/****************************************************************
* Video mode register definitions
****************************************************************/
static u8 sequ_01[] VAR16 = { 0x08, 0x03, 0x00, 0x02 };
static u8 crtc_01[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
0xff };
static u8 actl_01[] VAR16 = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x0c, 0x00, 0x0f, 0x08 };
static u8 grdc_01[] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff };
static u8 sequ_03[] VAR16 = { 0x00, 0x03, 0x00, 0x02 };
static u8 crtc_03[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
0xff };
static u8 sequ_04[] VAR16 = { 0x09, 0x03, 0x00, 0x02 };
static u8 crtc_04[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
0xff };
static u8 actl_04[] VAR16 = {
0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x01, 0x00, 0x03, 0x00 };
static u8 grdc_04[] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff };
static u8 sequ_06[] VAR16 = { 0x01, 0x01, 0x00, 0x06 };
static u8 crtc_06[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2,
0xff };
static u8 actl_06[] VAR16 = {
0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x01, 0x00, 0x01, 0x00 };
static u8 grdc_06[] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff };
static u8 crtc_07[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
0xff };
static u8 actl_07[] VAR16 = {
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x0e, 0x00, 0x0f, 0x08 };
static u8 grdc_07[] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff };
static u8 sequ_0d[] VAR16 = { 0x09, 0x0f, 0x00, 0x06 };
static u8 crtc_0d[] VAR16 = {
0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3,
0xff };
static u8 actl_0d[] VAR16 = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x01, 0x00, 0x0f, 0x00 };
static u8 grdc_0d[] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff };
static u8 sequ_0e[] VAR16 = { 0x01, 0x0f, 0x00, 0x06 };
static u8 crtc_0e[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3,
0xff };
static u8 crtc_0f[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
0xff };
static u8 actl_0f[] VAR16 = {
0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00 };
static u8 actl_10[] VAR16 = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x01, 0x00, 0x0f, 0x00 };
static u8 crtc_11[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
0xff };
static u8 actl_11[] VAR16 = {
0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f,
0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f,
0x01, 0x00, 0x0f, 0x00 };
static u8 sequ_13[] VAR16 = { 0x01, 0x0f, 0x00, 0x0e };
static u8 crtc_13[] VAR16 = {
0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
0xff };
static u8 actl_13[] VAR16 = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x41, 0x00, 0x0f, 0x00 };
static u8 grdc_13[] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff };
static u8 crtc_6A[] VAR16 = {
0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3,
0xff };
#define PAL(x) x, sizeof(x)
struct stdvga_mode_s {
u16 mode;
struct vgamode_s info;
u8 *dac;
u16 dacsize;
u8 *sequ_regs;
u8 miscreg;
u8 *crtc_regs;
u8 *actl_regs;
u8 *grdc_regs;
};
static struct stdvga_mode_s vga_modes[] VAR16 = {
//mode { model tx ty bpp cw ch sstart } dac
// sequ misc crtc actl grdc
{0x00, { MM_TEXT, 40, 25, 4, 9, 16, SEG_CTEXT }, PAL(pal_ega)
, sequ_01, 0x67, crtc_01, actl_01, grdc_01},
{0x01, { MM_TEXT, 40, 25, 4, 9, 16, SEG_CTEXT }, PAL(pal_ega)
, sequ_01, 0x67, crtc_01, actl_01, grdc_01},
{0x02, { MM_TEXT, 80, 25, 4, 9, 16, SEG_CTEXT }, PAL(pal_ega)
, sequ_03, 0x67, crtc_03, actl_01, grdc_01},
{0x03, { MM_TEXT, 80, 25, 4, 9, 16, SEG_CTEXT }, PAL(pal_ega)
, sequ_03, 0x67, crtc_03, actl_01, grdc_01},
{0x04, { MM_CGA, 320, 200, 2, 8, 8, SEG_CTEXT }, PAL(pal_cga)
, sequ_04, 0x63, crtc_04, actl_04, grdc_04},
{0x05, { MM_CGA, 320, 200, 2, 8, 8, SEG_CTEXT }, PAL(pal_cga)
, sequ_04, 0x63, crtc_04, actl_04, grdc_04},
{0x06, { MM_CGA, 640, 200, 1, 8, 8, SEG_CTEXT }, PAL(pal_cga)
, sequ_06, 0x63, crtc_06, actl_06, grdc_06},
{0x07, { MM_TEXT, 80, 25, 4, 9, 16, SEG_MTEXT }, PAL(pal_mda)
, sequ_03, 0x66, crtc_07, actl_07, grdc_07},
{0x0D, { MM_PLANAR, 320, 200, 4, 8, 8, SEG_GRAPH }, PAL(pal_cga)
, sequ_0d, 0x63, crtc_0d, actl_0d, grdc_0d},
{0x0E, { MM_PLANAR, 640, 200, 4, 8, 8, SEG_GRAPH }, PAL(pal_cga)
, sequ_0e, 0x63, crtc_0e, actl_0d, grdc_0d},
{0x0F, { MM_PLANAR, 640, 350, 1, 8, 14, SEG_GRAPH }, PAL(pal_mda)
, sequ_0e, 0xa3, crtc_0f, actl_0f, grdc_0d},
{0x10, { MM_PLANAR, 640, 350, 4, 8, 14, SEG_GRAPH }, PAL(pal_ega)
, sequ_0e, 0xa3, crtc_0f, actl_10, grdc_0d},
{0x11, { MM_PLANAR, 640, 480, 1, 8, 16, SEG_GRAPH }, PAL(pal_ega)
, sequ_0e, 0xe3, crtc_11, actl_11, grdc_0d},
{0x12, { MM_PLANAR, 640, 480, 4, 8, 16, SEG_GRAPH }, PAL(pal_ega)
, sequ_0e, 0xe3, crtc_11, actl_10, grdc_0d},
{0x13, { MM_PACKED, 320, 200, 8, 8, 8, SEG_GRAPH }, PAL(pal_vga)
, sequ_13, 0x63, crtc_13, actl_13, grdc_13},
{0x6A, { MM_PLANAR, 800, 600, 4, 8, 16, SEG_GRAPH }, PAL(pal_ega)
, sequ_0e, 0xe3, crtc_6A, actl_10, grdc_0d},
};
/****************************************************************
* Mode functions
****************************************************************/
static int
is_stdvga_mode(struct vgamode_s *vmode_g)
{
return (vmode_g >= &vga_modes[0].info
&& vmode_g <= &vga_modes[ARRAY_SIZE(vga_modes)-1].info);
}
struct vgamode_s *
stdvga_find_mode(int mode)
{
int i;
for (i = 0; i < ARRAY_SIZE(vga_modes); i++) {
struct stdvga_mode_s *stdmode_g = &vga_modes[i];
if (GET_GLOBAL(stdmode_g->mode) == mode)
return &stdmode_g->info;
}
return NULL;
}
void
stdvga_list_modes(u16 seg, u16 *dest, u16 *last)
{
int i;
for (i = 0; i < ARRAY_SIZE(vga_modes) && dest < last; i++) {
struct stdvga_mode_s *stdmode_g = &vga_modes[i];
u16 mode = GET_GLOBAL(stdmode_g->mode);
if (mode == 0xffff)
continue;
SET_FARVAR(seg, *dest, mode);
dest++;
}
SET_FARVAR(seg, *dest, 0xffff);
}
static struct video_save_pointer_s video_save_pointer_table VAR16;
static struct video_param_s video_param_table[29] VAR16;
void
stdvga_build_video_param(void)
{
SET_BDA(video_savetable
, SEGOFF(get_global_seg(), (u32)&video_save_pointer_table));
SET_VGA(video_save_pointer_table.videoparam
, SEGOFF(get_global_seg(), (u32)video_param_table));
static u8 parammodes[] VAR16 = {
0, 0, 0, 0, 0x04, 0x05, 0x06, 0x07,
0, 0, 0, 0, 0, 0x0d, 0x0e, 0,
0, 0x0f, 0x10, 0, 0, 0, 0, 0x01,
0x03, 0x07, 0x11, 0x12, 0x13
};
int i;
for (i=0; i<ARRAY_SIZE(parammodes); i++) {
int mode = GET_GLOBAL(parammodes[i]);
if (! mode)
continue;
struct video_param_s *vparam_g = &video_param_table[i];
struct vgamode_s *vmode_g = stdvga_find_mode(mode);
if (!vmode_g)
continue;
int width = GET_GLOBAL(vmode_g->width);
int height = GET_GLOBAL(vmode_g->height);
u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
int cheight = GET_GLOBAL(vmode_g->cheight);
if (memmodel == MM_TEXT) {
SET_VGA(vparam_g->twidth, width);
SET_VGA(vparam_g->theightm1, height-1);
} else {
int cwidth = GET_GLOBAL(vmode_g->cwidth);
SET_VGA(vparam_g->twidth, width / cwidth);
SET_VGA(vparam_g->theightm1, (height / cheight) - 1);
}
SET_VGA(vparam_g->cheight, cheight);
SET_VGA(vparam_g->slength, calc_page_size(memmodel, width, height));
struct stdvga_mode_s *stdmode_g = container_of(
vmode_g, struct stdvga_mode_s, info);
memcpy_far(get_global_seg(), vparam_g->sequ_regs
, get_global_seg(), GET_GLOBAL(stdmode_g->sequ_regs)
, ARRAY_SIZE(vparam_g->sequ_regs));
SET_VGA(vparam_g->miscreg, GET_GLOBAL(stdmode_g->miscreg));
memcpy_far(get_global_seg(), vparam_g->crtc_regs
, get_global_seg(), GET_GLOBAL(stdmode_g->crtc_regs)
, ARRAY_SIZE(vparam_g->crtc_regs));
memcpy_far(get_global_seg(), vparam_g->actl_regs
, get_global_seg(), GET_GLOBAL(stdmode_g->actl_regs)
, ARRAY_SIZE(vparam_g->actl_regs));
memcpy_far(get_global_seg(), vparam_g->grdc_regs
, get_global_seg(), GET_GLOBAL(stdmode_g->grdc_regs)
, ARRAY_SIZE(vparam_g->grdc_regs));
}
// Fill available legacy modes in video_func_static table
u32 modes = 0;
for (i = 0; i < ARRAY_SIZE(vga_modes); i++) {
u16 mode = GET_GLOBAL(vga_modes[i].mode);
if (mode <= 0x13)
modes |= 1<<mode;
}
SET_VGA(static_functionality.modes, modes);
}
void
stdvga_override_crtc(int mode, u8 *crtc)
{
struct vgamode_s *vmode_g = stdvga_find_mode(mode);
if (!vmode_g)
return;
struct stdvga_mode_s *stdmode_g = container_of(
vmode_g, struct stdvga_mode_s, info);
SET_VGA(stdmode_g->crtc_regs, crtc);
}
static void
clear_screen(struct vgamode_s *curmode_g)
{
switch (GET_GLOBAL(curmode_g->memmodel)) {
case MM_TEXT:
memset16_far(GET_GLOBAL(curmode_g->sstart), 0, 0x0720, 32*1024);
break;
case MM_CGA:
memset16_far(GET_GLOBAL(curmode_g->sstart), 0, 0x0000, 32*1024);
break;
default:
memset16_far(GET_GLOBAL(curmode_g->sstart), 0, 0x0000, 64*1024);
}
}
int
stdvga_set_mode(struct vgamode_s *vmode_g, int flags)
{
if (! is_stdvga_mode(vmode_g)) {
warn_internalerror();
return -1;
}
struct stdvga_mode_s *stdmode_g = container_of(
vmode_g, struct stdvga_mode_s, info);
// if palette loading (bit 3 of modeset ctl = 0)
if (!(flags & MF_NOPALETTE)) { // Set the PEL mask
stdvga_pelmask_write(0xff);
// From which palette
u8 *palette_g = GET_GLOBAL(stdmode_g->dac);
u16 palsize = GET_GLOBAL(stdmode_g->dacsize) / 3;
// Always 256*3 values
stdvga_dac_write_many(get_global_seg(), palette_g, 0, palsize);
int i;
for (i = palsize; i < 0x0100; i++) {
struct vbe_palette_entry rgb = { };
stdvga_dac_write(i, rgb);
}
if (flags & MF_GRAYSUM)
stdvga_perform_gray_scale_summing(0x00, 0x100);
}
// Set Attribute Ctl
u8 *regs = GET_GLOBAL(stdmode_g->actl_regs);
int i;
for (i = 0; i <= 0x13; i++)
stdvga_attr_write(i, GET_GLOBAL(regs[i]));
stdvga_attr_write(0x14, 0x00);
// Set Sequencer Ctl
stdvga_sequ_write(0x00, 0x03);
regs = GET_GLOBAL(stdmode_g->sequ_regs);
for (i = 1; i <= 4; i++)
stdvga_sequ_write(i, GET_GLOBAL(regs[i - 1]));
// Set Grafx Ctl
regs = GET_GLOBAL(stdmode_g->grdc_regs);
for (i = 0; i <= 8; i++)
stdvga_grdc_write(i, GET_GLOBAL(regs[i]));
// Set CRTC address VGA or MDA
u8 miscreg = GET_GLOBAL(stdmode_g->miscreg);
u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
if (!(miscreg & 1))
crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
// Disable CRTC write protection
stdvga_crtc_write(crtc_addr, 0x11, 0x00);
// Set CRTC regs
regs = GET_GLOBAL(stdmode_g->crtc_regs);
for (i = 0; i <= 0x18; i++)
stdvga_crtc_write(crtc_addr, i, GET_GLOBAL(regs[i]));
// Set the misc register
stdvga_misc_write(miscreg);
// Enable video
stdvga_attrindex_write(0x20);
// Clear screen
if (!(flags & MF_NOCLEARMEM))
clear_screen(vmode_g);
// Write the fonts in memory
u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
if (memmodel == MM_TEXT)
stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16);
return 0;
}
// Load the standard palette associated with 8bpp packed pixel vga modes.
void
stdvga_set_packed_palette(void)
{
stdvga_dac_write_many(get_global_seg(), pal_vga, 0, sizeof(pal_vga) / 3);
}
+104
View File
@@ -0,0 +1,104 @@
// Common svga mode definitions
//
// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2011 Julian Pidancet <julian.pidancet@citrix.com>
// Copyright (C) 2002 Jeroen Janssen
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "stdvga.h" // SEG_GRAPH
#include "vgabios.h" // VAR16
#include "svgamodes.h"
struct generic_svga_mode svga_modes[] VAR16 = {
/* standard modes */
{ 0x100, { MM_PACKED, 640, 400, 8, 8, 16, SEG_GRAPH } },
{ 0x101, { MM_PACKED, 640, 480, 8, 8, 16, SEG_GRAPH } },
{ 0x102, { MM_PLANAR, 800, 600, 4, 8, 16, SEG_GRAPH } },
{ 0x103, { MM_PACKED, 800, 600, 8, 8, 16, SEG_GRAPH } },
{ 0x104, { MM_PLANAR, 1024, 768, 4, 8, 16, SEG_GRAPH } },
{ 0x105, { MM_PACKED, 1024, 768, 8, 8, 16, SEG_GRAPH } },
{ 0x106, { MM_PLANAR, 1280, 1024, 4, 8, 16, SEG_GRAPH } },
{ 0x107, { MM_PACKED, 1280, 1024, 8, 8, 16, SEG_GRAPH } },
{ 0x10D, { MM_DIRECT, 320, 200, 15, 8, 16, SEG_GRAPH } },
{ 0x10E, { MM_DIRECT, 320, 200, 16, 8, 16, SEG_GRAPH } },
{ 0x10F, { MM_DIRECT, 320, 200, 24, 8, 16, SEG_GRAPH } },
{ 0x110, { MM_DIRECT, 640, 480, 15, 8, 16, SEG_GRAPH } },
{ 0x111, { MM_DIRECT, 640, 480, 16, 8, 16, SEG_GRAPH } },
{ 0x112, { MM_DIRECT, 640, 480, 24, 8, 16, SEG_GRAPH } },
{ 0x113, { MM_DIRECT, 800, 600, 15, 8, 16, SEG_GRAPH } },
{ 0x114, { MM_DIRECT, 800, 600, 16, 8, 16, SEG_GRAPH } },
{ 0x115, { MM_DIRECT, 800, 600, 24, 8, 16, SEG_GRAPH } },
{ 0x116, { MM_DIRECT, 1024, 768, 15, 8, 16, SEG_GRAPH } },
{ 0x117, { MM_DIRECT, 1024, 768, 16, 8, 16, SEG_GRAPH } },
{ 0x118, { MM_DIRECT, 1024, 768, 24, 8, 16, SEG_GRAPH } },
{ 0x119, { MM_DIRECT, 1280, 1024, 15, 8, 16, SEG_GRAPH } },
{ 0x11A, { MM_DIRECT, 1280, 1024, 16, 8, 16, SEG_GRAPH } },
{ 0x11B, { MM_DIRECT, 1280, 1024, 24, 8, 16, SEG_GRAPH } },
{ 0x11C, { MM_PACKED, 1600, 1200, 8, 8, 16, SEG_GRAPH } },
{ 0x11D, { MM_DIRECT, 1600, 1200, 15, 8, 16, SEG_GRAPH } },
{ 0x11E, { MM_DIRECT, 1600, 1200, 16, 8, 16, SEG_GRAPH } },
{ 0x11F, { MM_DIRECT, 1600, 1200, 24, 8, 16, SEG_GRAPH } },
/* other modes */
{ 0x140, { MM_DIRECT, 320, 200, 32, 8, 16, SEG_GRAPH } },
{ 0x141, { MM_DIRECT, 640, 400, 32, 8, 16, SEG_GRAPH } },
{ 0x142, { MM_DIRECT, 640, 480, 32, 8, 16, SEG_GRAPH } },
{ 0x143, { MM_DIRECT, 800, 600, 32, 8, 16, SEG_GRAPH } },
{ 0x144, { MM_DIRECT, 1024, 768, 32, 8, 16, SEG_GRAPH } },
{ 0x145, { MM_DIRECT, 1280, 1024, 32, 8, 16, SEG_GRAPH } },
{ 0x146, { MM_PACKED, 320, 200, 8, 8, 16, SEG_GRAPH } },
{ 0x147, { MM_DIRECT, 1600, 1200, 32, 8, 16, SEG_GRAPH } },
{ 0x148, { MM_PACKED, 1152, 864, 8, 8, 16, SEG_GRAPH } },
{ 0x149, { MM_DIRECT, 1152, 864, 15, 8, 16, SEG_GRAPH } },
{ 0x14a, { MM_DIRECT, 1152, 864, 16, 8, 16, SEG_GRAPH } },
{ 0x14b, { MM_DIRECT, 1152, 864, 24, 8, 16, SEG_GRAPH } },
{ 0x14c, { MM_DIRECT, 1152, 864, 32, 8, 16, SEG_GRAPH } },
{ 0x175, { MM_DIRECT, 1280, 768, 16, 8, 16, SEG_GRAPH } },
{ 0x176, { MM_DIRECT, 1280, 768, 24, 8, 16, SEG_GRAPH } },
{ 0x177, { MM_DIRECT, 1280, 768, 32, 8, 16, SEG_GRAPH } },
{ 0x178, { MM_DIRECT, 1280, 800, 16, 8, 16, SEG_GRAPH } },
{ 0x179, { MM_DIRECT, 1280, 800, 24, 8, 16, SEG_GRAPH } },
{ 0x17a, { MM_DIRECT, 1280, 800, 32, 8, 16, SEG_GRAPH } },
{ 0x17b, { MM_DIRECT, 1280, 960, 16, 8, 16, SEG_GRAPH } },
{ 0x17c, { MM_DIRECT, 1280, 960, 24, 8, 16, SEG_GRAPH } },
{ 0x17d, { MM_DIRECT, 1280, 960, 32, 8, 16, SEG_GRAPH } },
{ 0x17e, { MM_DIRECT, 1440, 900, 16, 8, 16, SEG_GRAPH } },
{ 0x17f, { MM_DIRECT, 1440, 900, 24, 8, 16, SEG_GRAPH } },
{ 0x180, { MM_DIRECT, 1440, 900, 32, 8, 16, SEG_GRAPH } },
{ 0x181, { MM_DIRECT, 1400, 1050, 16, 8, 16, SEG_GRAPH } },
{ 0x182, { MM_DIRECT, 1400, 1050, 24, 8, 16, SEG_GRAPH } },
{ 0x183, { MM_DIRECT, 1400, 1050, 32, 8, 16, SEG_GRAPH } },
{ 0x184, { MM_DIRECT, 1680, 1050, 16, 8, 16, SEG_GRAPH } },
{ 0x185, { MM_DIRECT, 1680, 1050, 24, 8, 16, SEG_GRAPH } },
{ 0x186, { MM_DIRECT, 1680, 1050, 32, 8, 16, SEG_GRAPH } },
{ 0x187, { MM_DIRECT, 1920, 1200, 16, 8, 16, SEG_GRAPH } },
{ 0x188, { MM_DIRECT, 1920, 1200, 24, 8, 16, SEG_GRAPH } },
{ 0x189, { MM_DIRECT, 1920, 1200, 32, 8, 16, SEG_GRAPH } },
{ 0x18a, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } },
{ 0x18b, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } },
{ 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } },
{ 0x18d, { MM_DIRECT, 1280, 720, 16, 8, 16, SEG_GRAPH } },
{ 0x18e, { MM_DIRECT, 1280, 720, 24, 8, 16, SEG_GRAPH } },
{ 0x18f, { MM_DIRECT, 1280, 720, 32, 8, 16, SEG_GRAPH } },
{ 0x190, { MM_DIRECT, 1920, 1080, 16, 8, 16, SEG_GRAPH } },
{ 0x191, { MM_DIRECT, 1920, 1080, 24, 8, 16, SEG_GRAPH } },
{ 0x192, { MM_DIRECT, 1920, 1080, 32, 8, 16, SEG_GRAPH } },
/* custom resolutions for 16:9 displays */
{ 0x193, { MM_DIRECT, 1600, 900, 16, 8, 16, SEG_GRAPH } },
{ 0x194, { MM_DIRECT, 1600, 900, 24, 8, 16, SEG_GRAPH } },
{ 0x195, { MM_DIRECT, 1600, 900, 32, 8, 16, SEG_GRAPH } },
{ 0x196, { MM_DIRECT, 2560, 1440, 16, 8, 16, SEG_GRAPH } },
{ 0x197, { MM_DIRECT, 2560, 1440, 24, 8, 16, SEG_GRAPH } },
{ 0x198, { MM_DIRECT, 2560, 1440, 32, 8, 16, SEG_GRAPH } },
/* 4k modes */
{ 0x199, { MM_DIRECT, 3840, 2160, 16, 8, 16, SEG_GRAPH } },
{ 0x19a, { MM_DIRECT, 3840, 2160, 32, 8, 16, SEG_GRAPH } },
{ 0x19b, { MM_DIRECT, 4096, 2160, 16, 8, 16, SEG_GRAPH } },
{ 0x19c, { MM_DIRECT, 4096, 2160, 32, 8, 16, SEG_GRAPH } },
{ 0x19d, { MM_DIRECT, 5120, 2160, 16, 8, 16, SEG_GRAPH } },
{ 0x19e, { MM_DIRECT, 5120, 2160, 32, 8, 16, SEG_GRAPH } },
};
unsigned int svga_mcount VAR16 = ARRAY_SIZE(svga_modes);
+12
View File
@@ -0,0 +1,12 @@
#ifndef __SVGAMODES_H
#define __SVGAMODES_H
struct generic_svga_mode {
u16 mode;
struct vgamode_s info;
};
extern struct generic_svga_mode svga_modes[];
extern unsigned int svga_mcount;
#endif /* __SVGAMODES_H */
+96
View File
@@ -0,0 +1,96 @@
// Virtual software based cursor support
//
// Copyright (C) 2014-2016 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_BDA
#include "bregs.h" // struct bregs
#include "vgabios.h" // get_cursor_pos
#include "vgafb.h" // handle_gfx_op
#include "vgautil.h" // swcursor_check_event
// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell
static void
gfx_set_swcursor(struct vgamode_s *curmode_g, int enable, struct cursorpos cp)
{
u16 cursor_type = get_cursor_shape();
u8 start = cursor_type >> 8, end = cursor_type & 0xff;
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.x = cp.x * 8;
int cheight = GET_BDA(char_height);
op.y = cp.y * cheight + start;
int i;
for (i = start; i < cheight && i <= end; i++, op.y++) {
op.op = GO_READ8;
handle_gfx_op(&op);
int j;
for (j = 0; j < 8; j++)
op.pixels[j] ^= 0x07;
op.op = GO_WRITE8;
handle_gfx_op(&op);
}
}
// Draw/undraw a cursor on the screen
static void
set_swcursor(int enable)
{
u8 flags = GET_BDA_EXT(flags);
if (!!(flags & BF_SWCURSOR) == enable)
// Already in requested mode.
return;
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return;
struct cursorpos cp = get_cursor_pos(GET_BDA(video_page));
if (cp.x >= GET_BDA(video_cols) || cp.y > GET_BDA(video_rows)
|| GET_BDA(cursor_type) >= 0x2000)
// Cursor not visible
return;
SET_BDA_EXT(flags, (flags & ~BF_SWCURSOR) | (enable ? BF_SWCURSOR : 0));
if (GET_GLOBAL(curmode_g->memmodel) != MM_TEXT) {
gfx_set_swcursor(curmode_g, enable, cp);
return;
}
// In text mode, swap foreground and background attributes for cursor
void *dest_far = text_address(cp) + 1;
u8 attr = GET_FARVAR(GET_GLOBAL(curmode_g->sstart), *(u8*)dest_far);
attr = (attr >> 4) | (attr << 4);
SET_FARVAR(GET_GLOBAL(curmode_g->sstart), *(u8*)dest_far, attr);
}
// Disable virtual cursor if a vgabios call accesses the framebuffer
void
swcursor_pre_handle10(struct bregs *regs)
{
if (!vga_emulate_text())
return;
switch (regs->ah) {
case 0x4f:
if (!CONFIG_VGA_VBE || regs->al != 0x02)
break;
// NO BREAK
case 0x00 ... 0x02:
case 0x05 ... 0x0e:
case 0x13:
set_swcursor(0);
break;
default:
break;
}
}
// Called by periodic (18.2hz) timer
void
swcursor_check_event(void)
{
if (!vga_emulate_text())
return;
set_swcursor(GET_BDA(timer_counter) % 18 < 9);
}
+517
View File
@@ -0,0 +1,517 @@
// Video Bios Extensions handlers
//
// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2011 Julian Pidancet <julian.pidancet@citrix.com>
// Copyright (C) 2001-2008 the LGPL VGABios developers Team
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_GLOBAL
#include "bregs.h" // struct bregs
#include "config.h" // CONFIG_*
#include "output.h" // dprintf
#include "std/vbe.h" // struct vbe_info
#include "string.h" // memset_far
#include "vgabios.h" // get_current_mode
#include "vgahw.h" // vgahw_set_mode
#include "vgautil.h" // handle_104f
#define VBE_OEM_STRING "SeaBIOS VBE(C) 2011"
#define VBE_VENDOR_STRING "SeaBIOS Developers"
#define VBE_PRODUCT_STRING "SeaBIOS VBE Adapter"
#define VBE_REVISION_STRING "Rev. 1"
u32 VBE_total_memory VAR16 = 256 * 1024;
u32 VBE_capabilities VAR16;
u32 VBE_framebuffer VAR16;
u16 VBE_win_granularity VAR16;
u8 VBE_edid[256] VAR16;
static void
vbe_104f00(struct bregs *regs)
{
u16 seg = regs->es;
struct vbe_info *info = (void*)(regs->di+0);
size_t info_size = offsetof(struct vbe_info, oem_data);
if (GET_FARVAR(seg, info->signature) == VBE2_SIGNATURE) {
dprintf(4, "Get VBE Controller: VBE2 Signature found\n");
info_size = sizeof(*info);
} else if (GET_FARVAR(seg, info->signature) == VESA_SIGNATURE) {
dprintf(4, "Get VBE Controller: VESA Signature found\n");
} else {
dprintf(4, "Get VBE Controller: Invalid Signature\n");
}
memset_far(seg, info, 0, info_size);
SET_FARVAR(seg, info->signature, VESA_SIGNATURE);
SET_FARVAR(seg, info->version, 0x0300);
SET_FARVAR(seg, info->oem_string,
SEGOFF(get_global_seg(), (u32)VBE_OEM_STRING));
SET_FARVAR(seg, info->capabilities, GET_GLOBAL(VBE_capabilities));
/* We generate our mode list in the reserved field of the info block */
u16 *destmode = (void*)info->reserved;
SET_FARVAR(seg, info->video_mode, SEGOFF(seg, (u32)destmode));
/* Total memory (in 64k blocks) */
SET_FARVAR(seg, info->total_memory
, GET_GLOBAL(VBE_total_memory) / (64*1024));
SET_FARVAR(seg, info->oem_vendor_string,
SEGOFF(get_global_seg(), (u32)VBE_VENDOR_STRING));
SET_FARVAR(seg, info->oem_product_string,
SEGOFF(get_global_seg(), (u32)VBE_PRODUCT_STRING));
SET_FARVAR(seg, info->oem_revision_string,
SEGOFF(get_global_seg(), (u32)VBE_REVISION_STRING));
/* Fill list of modes */
u16 *last = (void*)&info->reserved[sizeof(info->reserved)];
vgahw_list_modes(seg, destmode, last - 1);
regs->ax = 0x004f;
}
static void
vbe_104f01(struct bregs *regs)
{
u16 seg = regs->es;
struct vbe_mode_info *info = (void*)(regs->di+0);
u16 mode = regs->cx;
dprintf(1, "VBE mode info request: %x\n", mode);
struct vgamode_s *vmode_g = vgahw_find_mode(mode & ~MF_VBEFLAGS);
if (! vmode_g) {
dprintf(1, "VBE mode %x not found\n", mode);
regs->ax = 0x014f;
return;
}
memset_far(seg, info, 0, sizeof(*info));
// Basic information about video controller.
u32 win_granularity = GET_GLOBAL(VBE_win_granularity);
SET_FARVAR(seg, info->winA_attributes,
(win_granularity ? VBE_WINDOW_ATTRIBUTE_RELOCATABLE : 0) |
VBE_WINDOW_ATTRIBUTE_READABLE |
VBE_WINDOW_ATTRIBUTE_WRITEABLE);
SET_FARVAR(seg, info->winB_attributes, 0);
SET_FARVAR(seg, info->win_granularity, win_granularity);
SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */
SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart));
SET_FARVAR(seg, info->winB_seg, 0x0);
extern void entry_104f05(void);
SET_FARVAR(seg, info->win_func_ptr
, SEGOFF(get_global_seg(), (u32)entry_104f05));
// Basic information about mode.
int width = GET_GLOBAL(vmode_g->width);
int height = GET_GLOBAL(vmode_g->height);
int linesize = vgahw_minimum_linelength(vmode_g);
SET_FARVAR(seg, info->bytes_per_scanline, linesize);
SET_FARVAR(seg, info->xres, width);
SET_FARVAR(seg, info->yres, height);
SET_FARVAR(seg, info->xcharsize, GET_GLOBAL(vmode_g->cwidth));
SET_FARVAR(seg, info->ycharsize, GET_GLOBAL(vmode_g->cheight));
int depth = GET_GLOBAL(vmode_g->depth);
SET_FARVAR(seg, info->bits_per_pixel, depth);
u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
SET_FARVAR(seg, info->mem_model, memmodel);
SET_FARVAR(seg, info->reserved0, 1);
// Mode specific info.
u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED |
VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE |
VBE_MODE_ATTRIBUTE_COLOR_MODE |
VBE_MODE_ATTRIBUTE_GRAPHICS_MODE |
VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE;
u32 framebuffer = 0;
int planes = 1, banks = 1;
u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024);
switch (memmodel) {
case MM_TEXT:
mode_attr &= ~VBE_MODE_ATTRIBUTE_GRAPHICS_MODE;
mode_attr |= VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT;
if (GET_GLOBAL(vmode_g->sstart) == SEG_MTEXT)
mode_attr &= ~VBE_MODE_ATTRIBUTE_COLOR_MODE;
pages = 1;
break;
case MM_CGA:
pages = 1;
banks = 2;
SET_FARVAR(seg, info->bank_size, 8);
break;
case MM_PLANAR:
planes = 4;
pages /= 4;
break;
default:
framebuffer = GET_GLOBAL(VBE_framebuffer);
if (framebuffer)
mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE;
break;
}
if (pages > 128)
pages = 128;
if (pages < 2)
pages++;
SET_FARVAR(seg, info->mode_attributes, mode_attr);
SET_FARVAR(seg, info->planes, planes);
SET_FARVAR(seg, info->pages, pages - 1);
SET_FARVAR(seg, info->banks, banks);
// Pixel color breakdown
u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos;
switch (depth) {
case 15: r_size = 5; r_pos = 10; g_size = 5; g_pos = 5;
b_size = 5; b_pos = 0; a_size = 1; a_pos = 15; break;
case 16: r_size = 5; r_pos = 11; g_size = 6; g_pos = 5;
b_size = 5; b_pos = 0; a_size = 0; a_pos = 0; break;
case 24: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8;
b_size = 8; b_pos = 0; a_size = 0; a_pos = 0; break;
case 32: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8;
b_size = 8; b_pos = 0; a_size = 8; a_pos = 24;
SET_FARVAR(seg, info->directcolor_info,
VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE);
break;
default: r_size = 0; r_pos = 0; g_size = 0; g_pos = 0;
b_size = 0; b_pos = 0; a_size = 0; a_pos = 0; break;
}
SET_FARVAR(seg, info->red_size, r_size);
SET_FARVAR(seg, info->red_pos, r_pos);
SET_FARVAR(seg, info->green_size, g_size);
SET_FARVAR(seg, info->green_pos, g_pos);
SET_FARVAR(seg, info->blue_size, b_size);
SET_FARVAR(seg, info->blue_pos, b_pos);
SET_FARVAR(seg, info->alpha_size, a_size);
SET_FARVAR(seg, info->alpha_pos, a_pos);
// Linear framebuffer info.
if (framebuffer) {
SET_FARVAR(seg, info->phys_base, framebuffer);
SET_FARVAR(seg, info->reserved1, 0);
SET_FARVAR(seg, info->reserved2, 0);
SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize);
SET_FARVAR(seg, info->linear_pages, 0);
SET_FARVAR(seg, info->linear_red_size, r_size);
SET_FARVAR(seg, info->linear_red_pos, r_pos);
SET_FARVAR(seg, info->linear_green_size, g_size);
SET_FARVAR(seg, info->linear_green_pos, g_pos);
SET_FARVAR(seg, info->linear_blue_size, b_size);
SET_FARVAR(seg, info->linear_blue_pos, b_pos);
SET_FARVAR(seg, info->linear_alpha_size, a_size);
SET_FARVAR(seg, info->linear_alpha_pos, a_pos);
}
regs->ax = 0x004f;
}
static void
vbe_104f02(struct bregs *regs)
{
dprintf(1, "VBE mode set: %x\n", regs->bx);
int mode = regs->bx & ~MF_VBEFLAGS;
int flags = regs->bx & MF_VBEFLAGS;
int ret = vga_set_mode(mode, flags);
regs->ah = ret;
regs->al = 0x4f;
}
static void
vbe_104f03(struct bregs *regs)
{
regs->bx = GET_BDA_EXT(vbe_mode);
dprintf(1, "VBE current mode=%x\n", regs->bx);
regs->ax = 0x004f;
}
static void
vbe_104f04(struct bregs *regs)
{
u16 seg = regs->es;
void *data = (void*)(regs->bx+0);
u16 states = regs->cx;
u8 cmd = regs->dl;
if (states & ~0x0f || cmd > 2)
goto fail;
int ret = vgahw_save_restore(states | (cmd<<8), seg, data);
if (ret < 0)
goto fail;
if (cmd == 0)
regs->bx = DIV_ROUND_UP(ret, 64);
regs->ax = 0x004f;
return;
fail:
regs->ax = 0x014f;
}
void VISIBLE16
vbe_104f05(struct bregs *regs)
{
if (regs->bh > 1 || regs->bl > 1)
goto fail;
if (GET_BDA_EXT(vbe_mode) & MF_LINEARFB) {
regs->ah = VBE_RETURN_STATUS_INVALID;
return;
}
struct vgamode_s *curmode_g = get_current_mode();
if (! curmode_g)
goto fail;
if (regs->bh) {
int ret = vgahw_get_window(curmode_g, regs->bl);
if (ret < 0)
goto fail;
regs->dx = ret;
regs->ax = 0x004f;
return;
}
int ret = vgahw_set_window(curmode_g, regs->bl, regs->dx);
if (ret)
goto fail;
regs->ax = 0x004f;
return;
fail:
regs->ax = 0x014f;
}
static void
vbe_104f06(struct bregs *regs)
{
if (regs->bl > 0x02)
goto fail;
struct vgamode_s *curmode_g = get_current_mode();
if (! curmode_g)
goto fail;
int bpp = vga_bpp(curmode_g);
if (regs->bl == 0x00) {
int ret = vgahw_set_linelength(curmode_g
, DIV_ROUND_UP(regs->cx * bpp, 8));
if (ret)
goto fail;
} else if (regs->bl == 0x02) {
int ret = vgahw_set_linelength(curmode_g, regs->cx);
if (ret)
goto fail;
}
int linelength = vgahw_get_linelength(curmode_g);
if (linelength < 0)
goto fail;
regs->bx = linelength;
regs->cx = (linelength * 8) / bpp;
regs->dx = GET_GLOBAL(VBE_total_memory) / linelength;
regs->ax = 0x004f;
return;
fail:
regs->ax = 0x014f;
}
static void
vbe_104f07(struct bregs *regs)
{
struct vgamode_s *curmode_g = get_current_mode();
if (! curmode_g)
goto fail;
int bpp = vga_bpp(curmode_g);
int linelength = vgahw_get_linelength(curmode_g);
if (linelength < 0)
goto fail;
int ret;
switch (regs->bl) {
case 0x80:
case 0x00:
ret = vgahw_set_displaystart(
curmode_g, DIV_ROUND_UP(regs->cx * bpp, 8) + linelength * regs->dx);
if (ret)
goto fail;
break;
case 0x01:
ret = vgahw_get_displaystart(curmode_g);
if (ret < 0)
goto fail;
regs->dx = ret / linelength;
regs->cx = (ret % linelength) * 8 / bpp;
break;
default:
goto fail;
}
regs->ax = 0x004f;
return;
fail:
regs->ax = 0x014f;
}
static void
vbe_104f08(struct bregs *regs)
{
struct vgamode_s *curmode_g = get_current_mode();
if (! curmode_g)
goto fail;
u8 memmodel = GET_GLOBAL(curmode_g->memmodel);
if (memmodel == MM_DIRECT || memmodel == MM_YUV) {
regs->ax = 0x034f;
return;
}
if (regs->bl > 1)
goto fail;
if (regs->bl == 0) {
int ret = vgahw_set_dacformat(curmode_g, regs->bh);
if (ret < 0)
goto fail;
}
int ret = vgahw_get_dacformat(curmode_g);
if (ret < 0)
goto fail;
regs->bh = ret;
regs->ax = 0x004f;
return;
fail:
regs->ax = 0x014f;
}
static void
vbe_104f09(struct bregs *regs)
{
if (!CONFIG_VGA_STDVGA_PORTS) {
// DAC palette support only available on devices with stdvga ports
regs->ax = 0x0100;
return;
}
struct vgamode_s *curmode_g = get_current_mode();
if (! curmode_g)
goto fail;
u8 memmodel = GET_GLOBAL(curmode_g->memmodel);
u8 depth = GET_GLOBAL(curmode_g->depth);
if (memmodel == MM_DIRECT || memmodel == MM_YUV || depth > 8) {
regs->ax = 0x034f;
return;
}
if (regs->dh)
goto fail;
u8 start = regs->dl;
int count = regs->cx;
int max_colors = 1 << depth;
if (start + count > max_colors)
goto fail;
u16 seg = regs->es;
struct vbe_palette_entry *data_far = (void*)(regs->di+0);
int i;
switch (regs->bl) {
case 0x80:
case 0x00:
for (i = 0; i < count; i++) {
struct vbe_palette_entry rgb = GET_FARVAR(seg, data_far[i]);
stdvga_dac_write(start + i, rgb);
}
break;
case 0x01:
for (i = 0; i < count; i++) {
struct vbe_palette_entry rgb = stdvga_dac_read(start + i);
SET_FARVAR(seg, data_far[i], rgb);
}
break;
default:
goto fail;
}
regs->ax = 0x004f;
return;
fail:
regs->ax = 0x014f;
}
static void
vbe_104f0a(struct bregs *regs)
{
debug_stub(regs);
regs->ax = 0x0100;
}
static void
vbe_104f10(struct bregs *regs)
{
switch (regs->bl) {
case 0x00:
regs->bx = 0x0f30;
break;
case 0x01:
MASK_BDA_EXT(flags, BF_PM_MASK, regs->bh & BF_PM_MASK);
break;
case 0x02:
regs->bh = GET_BDA_EXT(flags) & BF_PM_MASK;
break;
default:
regs->ax = 0x014f;
return;
}
regs->ax = 0x004f;
}
static void
vbe_104f15(struct bregs *regs)
{
int offset;
switch (regs->bl) {
case 0x00:
if (GET_GLOBAL(VBE_edid[0]) != 0x00 ||
GET_GLOBAL(VBE_edid[1]) != 0xff)
goto err;
regs->bx = 0x0103;
break;
case 0x01:
offset = regs->dx * 128;
if (offset >= sizeof(VBE_edid))
goto err;
memcpy_far(regs->es, (void*)(regs->di+0),
get_global_seg(), VBE_edid + offset,
128);
break;
err:
default:
regs->ax = 0x014f;
return;
}
regs->ax = 0x004f;
}
static void
vbe_104fXX(struct bregs *regs)
{
debug_stub(regs);
regs->ax = 0x0100;
}
void noinline
handle_104f(struct bregs *regs)
{
if (!CONFIG_VGA_VBE) {
vbe_104fXX(regs);
return;
}
switch (regs->al) {
case 0x00: vbe_104f00(regs); break;
case 0x01: vbe_104f01(regs); break;
case 0x02: vbe_104f02(regs); break;
case 0x03: vbe_104f03(regs); break;
case 0x04: vbe_104f04(regs); break;
case 0x05: vbe_104f05(regs); break;
case 0x06: vbe_104f06(regs); break;
case 0x07: vbe_104f07(regs); break;
case 0x08: vbe_104f08(regs); break;
case 0x09: vbe_104f09(regs); break;
case 0x0a: vbe_104f0a(regs); break;
case 0x10: vbe_104f10(regs); break;
case 0x15: vbe_104f15(regs); break;
default: vbe_104fXX(regs); break;
}
}
+1133
View File
File diff suppressed because it is too large Load Diff
+88
View File
@@ -0,0 +1,88 @@
#ifndef __VGABIOS_H
#define __VGABIOS_H
#include "config.h" // CONFIG_VGA_EMULATE_TEXT
#include "farptr.h" // GET_FARVAR
#include "types.h" // u8
// Save/Restore flags
#define SR_HARDWARE 0x0001
#define SR_BDA 0x0002
#define SR_DAC 0x0004
#define SR_REGISTERS 0x0008
#define SR_SAVE 0x0100
#define SR_RESTORE 0x0200
// Mode flags
#define MF_LEGACY 0x0001
#define MF_GRAYSUM 0x0002
#define MF_NOPALETTE 0x0008
#define MF_CUSTOMCRTC 0x0800
#define MF_LINEARFB 0x4000
#define MF_NOCLEARMEM 0x8000
#define MF_VBEFLAGS 0xfe00
// Memory model types
#define MM_TEXT 0x00
#define MM_CGA 0x01
#define MM_HERCULES 0x02
#define MM_PLANAR 0x03
#define MM_PACKED 0x04
#define MM_NON_CHAIN_4_256 0x05
#define MM_DIRECT 0x06
#define MM_YUV 0x07
struct vgamode_s {
u8 memmodel;
u16 width;
u16 height;
u8 depth;
u8 cwidth;
u8 cheight;
u16 sstart;
};
// Custom internal storage in BDA (don't change here without also
// updating vgaentry.S)
#define VGA_CUSTOM_BDA 0xb9
struct vga_bda_s {
u8 flags;
u16 vbe_mode;
u16 vgamode_offset;
} PACKED;
#define BF_PM_MASK 0x0f
#define BF_EMULATE_TEXT 0x10
#define BF_SWCURSOR 0x20
#define BF_EXTRA_STACK 0x40
#define GET_BDA_EXT(var) \
GET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var)
#define SET_BDA_EXT(var, val) \
SET_FARVAR(SEG_BDA, ((struct vga_bda_s *)VGA_CUSTOM_BDA)->var, (val))
#define MASK_BDA_EXT(var, off, on) \
SET_BDA_EXT(var, (GET_BDA_EXT(var) & ~(off)) | (on))
static inline int vga_emulate_text(void) {
return CONFIG_VGA_EMULATE_TEXT && GET_BDA_EXT(flags) & BF_EMULATE_TEXT;
}
// Write to global variables (during "post" phase only)
#define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
// Debug settings
#define DEBUG_VGA_POST 1
#define DEBUG_VGA_10 9
// vgabios.c
int vga_bpp(struct vgamode_s *vmode_g);
u16 calc_page_size(u8 memmodel, u16 width, u16 height);
u16 get_cursor_shape(void);
struct cursorpos get_cursor_pos(u8 page);
int bda_save_restore(int cmd, u16 seg, void *data);
struct vgamode_s *get_current_mode(void);
int vga_set_mode(int mode, int flags);
extern struct video_func_static static_functionality;
#endif // vgabios.h
+164
View File
@@ -0,0 +1,164 @@
// Rom layout and bios assembler to C interface.
//
// Copyright (C) 2009-2013 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "asm-offsets.h" // BREGS_*
#include "config.h" // CONFIG_*
#include "entryfuncs.S" // ENTRY_*
/****************************************************************
* Rom Header
****************************************************************/
.section .rom.header
.code16
.global _rom_header, _rom_header_size, _rom_header_checksum
_rom_header:
.word 0xaa55
_rom_header_size:
.byte 0
_rom_header_entry:
jmp _optionrom_entry
_rom_header_checksum:
.byte 0
_rom_header_other:
.space 17
_rom_header_pcidata:
#if CONFIG_VGA_PCI == 1
.word rom_pci_data
#else
.word 0
#endif
_rom_header_pnpdata:
.word 0
_rom_header_other2:
.word 0
_rom_header_signature:
.asciz "IBM"
#if CONFIG_VGA_ATI
#include "ati-tables.S"
#endif
/****************************************************************
* Entry points
****************************************************************/
// This macro implements a call while avoiding instructions
// that old versions of x86emu have problems with.
.macro VGA_CALLL cfunc
#if CONFIG_VGA_FIXUP_ASM
pushw %ax
callw \cfunc
#else
calll \cfunc
#endif
.endm
// This macro is the same as ENTRY_ARG except VGA_CALLL is used.
.macro ENTRY_ARG_VGA cfunc
cli
cld
PUSHBREGS
movw %ss, %ax // Move %ss to %ds
movw %ax, %ds
movl %esp, %ebx // Backup %esp, then zero high bits
movzwl %sp, %esp
movl %esp, %eax // First arg is pointer to struct bregs
VGA_CALLL \cfunc
movl %ebx, %esp // Restore %esp (including high bits)
POPBREGS
.endm
DECLFUNC entry_104f05
entry_104f05:
ENTRY_ARG_VGA vbe_104f05
lretw
DECLFUNC _optionrom_entry
_optionrom_entry:
ENTRY_ARG_VGA vga_post
lretw
DECLFUNC entry_10
entry_10:
ENTRY_ARG_VGA handle_10
iretw
#define VGA_CUSTOM_BDA_FLAGS 0xb9
#define BF_EXTRA_STACK 0x40
// Entry point using extra stack
DECLFUNC entry_10_extrastack
entry_10_extrastack:
cli
cld
pushw %ds
pushl %eax
movw $SEG_BDA, %ax // Check if extra stack is enabled
movw %ax, %ds
testb $BF_EXTRA_STACK, VGA_CUSTOM_BDA_FLAGS
jz 1f
movw %cs:ExtraStackSeg, %ds // Set %ds:%eax to space on ExtraStack
movl $(CONFIG_VGA_EXTRA_STACK_SIZE-PUSHBREGS_size-16), %eax
SAVEBREGS_POP_DSEAX // Save registers on extra stack
movl %esp, PUSHBREGS_size+8(%eax)
movw %ss, PUSHBREGS_size+12(%eax)
popl BREGS_code(%eax)
popw BREGS_flags(%eax)
movw %ds, %dx // Setup %ss/%esp and call function
movw %dx, %ss
movl %eax, %esp
VGA_CALLL handle_10
movl %esp, %eax // Restore registers and return
movw PUSHBREGS_size+12(%eax), %ss
movl PUSHBREGS_size+8(%eax), %esp
popl %edx
popw %dx
pushw BREGS_flags(%eax)
pushl BREGS_code(%eax)
RESTOREBREGS_DSEAX
iretw
1: // Use regular entry point if the extra stack is disabled
popl %eax
popw %ds
jmp entry_10
// Timer irq handling
DECLFUNC entry_timer_hook
entry_timer_hook:
ENTRY handle_timer_hook
ljmpw *%cs:Timer_Hook_Resume
// Timer irq handling on extra stack
DECLFUNC entry_timer_hook_extrastack
entry_timer_hook_extrastack:
cli
cld
pushw %ds // Set %ds:%eax to space on ExtraStack
pushl %eax
movw %cs:ExtraStackSeg, %ds
movl $(CONFIG_VGA_EXTRA_STACK_SIZE-PUSHBREGS_size-8), %eax
SAVEBREGS_POP_DSEAX
movl %esp, PUSHBREGS_size(%eax)
movw %ss, PUSHBREGS_size+4(%eax)
movw %ds, %dx // Setup %ss/%esp and call function
movw %dx, %ss
movl %eax, %esp
calll handle_timer_hook
movl %esp, %eax // Restore registers and return
movw PUSHBREGS_size+4(%eax), %ss
movl PUSHBREGS_size(%eax), %esp
RESTOREBREGS_DSEAX
ljmpw *%cs:Timer_Hook_Resume
+660
View File
@@ -0,0 +1,660 @@
// Code for manipulating VGA framebuffers.
//
// Copyright (C) 2009-2014 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 "biosvar.h" // GET_BDA
#include "byteorder.h" // cpu_to_be16
#include "output.h" // dprintf
#include "stdvga.h" // stdvga_planar4_plane
#include "string.h" // memset_far
#include "vgabios.h" // get_current_mode
#include "vgafb.h" // vgafb_write_char
#include "vgahw.h" // vgahw_get_linelength
#include "vgautil.h" // VBE_framebuffer
static inline void
memmove_stride(u16 seg, void *dst, void *src, int copylen, int stride, int lines)
{
if (src < dst) {
dst += stride * (lines - 1);
src += stride * (lines - 1);
stride = -stride;
}
for (; lines; lines--, dst+=stride, src+=stride)
memcpy_far(seg, dst, seg, src, copylen);
}
static inline void
memset_stride(u16 seg, void *dst, u8 val, int setlen, int stride, int lines)
{
for (; lines; lines--, dst+=stride)
memset_far(seg, dst, val, setlen);
}
static inline void
memset16_stride(u16 seg, void *dst, u16 val, int setlen, int stride, int lines)
{
for (; lines; lines--, dst+=stride)
memset16_far(seg, dst, val, setlen);
}
/****************************************************************
* Basic stdvga graphic manipulation
****************************************************************/
static void
gfx_planar(struct gfx_op *op)
{
if (!CONFIG_VGA_STDVGA_PORTS)
return;
void *dest_far = (void*)(op->y * op->linelength + op->x / 8);
int plane;
switch (op->op) {
default:
case GO_READ8:
memset(op->pixels, 0, sizeof(op->pixels));
for (plane = 0; plane < 4; plane++) {
stdvga_planar4_plane(plane);
u8 data = GET_FARVAR(SEG_GRAPH, *(u8*)dest_far);
int pixel;
for (pixel=0; pixel<8; pixel++)
op->pixels[pixel] |= ((data>>(7-pixel)) & 1) << plane;
}
break;
case GO_WRITE8:
for (plane = 0; plane<4; plane++) {
stdvga_planar4_plane(plane);
u8 data = 0;
int pixel;
for (pixel=0; pixel<8; pixel++)
data |= ((op->pixels[pixel]>>plane) & 1) << (7-pixel);
SET_FARVAR(SEG_GRAPH, *(u8*)dest_far, data);
}
break;
case GO_MEMSET:
for (plane = 0; plane < 4; plane++) {
stdvga_planar4_plane(plane);
u8 data = (op->pixels[0] & (1<<plane)) ? 0xff : 0x00;
memset_stride(SEG_GRAPH, dest_far, data
, op->xlen / 8, op->linelength, op->ylen);
}
break;
case GO_MEMMOVE: ;
void *src_far = (void*)(op->srcy * op->linelength + op->x / 8);
for (plane = 0; plane < 4; plane++) {
stdvga_planar4_plane(plane);
memmove_stride(SEG_GRAPH, dest_far, src_far
, op->xlen / 8, op->linelength, op->ylen);
}
break;
}
stdvga_planar4_plane(-1);
}
static void
gfx_cga(struct gfx_op *op)
{
int bpp = GET_GLOBAL(op->curmode_g->depth);
void *dest_far = (void*)(op->y / 2 * op->linelength + op->x / 8 * bpp);
switch (op->op) {
default:
case GO_READ8:
if (op->y & 1)
dest_far += 0x2000;
if (bpp == 1) {
u8 data = GET_FARVAR(SEG_CTEXT, *(u8*)dest_far);
int pixel;
for (pixel=0; pixel<8; pixel++)
op->pixels[pixel] = (data >> (7-pixel)) & 1;
} else {
u16 data = GET_FARVAR(SEG_CTEXT, *(u16*)dest_far);
data = be16_to_cpu(data);
int pixel;
for (pixel=0; pixel<8; pixel++)
op->pixels[pixel] = (data >> ((7-pixel)*2)) & 3;
}
break;
case GO_WRITE8:
if (op->y & 1)
dest_far += 0x2000;
if (bpp == 1) {
u8 data = 0;
int pixel;
for (pixel=0; pixel<8; pixel++)
data |= (op->pixels[pixel] & 1) << (7-pixel);
SET_FARVAR(SEG_CTEXT, *(u8*)dest_far, data);
} else {
u16 data = 0;
int pixel;
for (pixel=0; pixel<8; pixel++)
data |= (op->pixels[pixel] & 3) << ((7-pixel) * 2);
data = cpu_to_be16(data);
SET_FARVAR(SEG_CTEXT, *(u16*)dest_far, data);
}
break;
case GO_MEMSET: ;
u8 data = op->pixels[0];
if (bpp == 1)
data = (data&1) | ((data&1)<<1);
data &= 3;
data |= (data<<2) | (data<<4) | (data<<6);
memset_stride(SEG_CTEXT, dest_far, data
, op->xlen / 8 * bpp, op->linelength, op->ylen / 2);
memset_stride(SEG_CTEXT, dest_far + 0x2000, data
, op->xlen / 8 * bpp, op->linelength, op->ylen / 2);
break;
case GO_MEMMOVE: ;
void *src_far = (void*)(op->srcy / 2 * op->linelength + op->x / 8 * bpp);
memmove_stride(SEG_CTEXT, dest_far, src_far
, op->xlen / 8 * bpp, op->linelength, op->ylen / 2);
memmove_stride(SEG_CTEXT, dest_far + 0x2000, src_far + 0x2000
, op->xlen / 8 * bpp, op->linelength, op->ylen / 2);
break;
}
}
static void
gfx_packed(struct gfx_op *op)
{
void *dest_far = (void*)(op->y * op->linelength + op->x);
switch (op->op) {
default:
case GO_READ8:
memcpy_far(GET_SEG(SS), op->pixels, SEG_GRAPH, dest_far, 8);
break;
case GO_WRITE8:
memcpy_far(SEG_GRAPH, dest_far, GET_SEG(SS), op->pixels, 8);
break;
case GO_MEMSET:
memset_stride(SEG_GRAPH, dest_far, op->pixels[0]
, op->xlen, op->linelength, op->ylen);
break;
case GO_MEMMOVE: ;
void *src_far = (void*)(op->srcy * op->linelength + op->x);
memmove_stride(SEG_GRAPH, dest_far, src_far
, op->xlen, op->linelength, op->ylen);
break;
}
}
/****************************************************************
* Direct framebuffers in high mem
****************************************************************/
// Use int 1587 call to copy memory to/from the framebuffer.
void memcpy_high(void *dest, void *src, u32 len)
{
u64 gdt[6];
gdt[2] = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)src);
gdt[3] = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)dest);
// Call int 1587 to copy data.
len/=2;
u32 flags;
u32 eax = 0x8700;
u32 si = (u32)&gdt;
SET_SEG(ES, GET_SEG(SS));
asm volatile(
"stc\n"
"int $0x15\n"
"cli\n"
"cld\n"
"pushfl\n"
"popl %0\n"
: "=r" (flags), "+a" (eax), "+S" (si), "+c" (len)
: : "cc", "memory");
}
static void
memmove_stride_high(void *dst, void *src, int copylen, int stride, int lines)
{
if (src < dst) {
dst += stride * (lines - 1);
src += stride * (lines - 1);
stride = -stride;
}
for (; lines; lines--, dst+=stride, src+=stride)
memcpy_high(dst, src, copylen);
}
// Map a CGA color to a "direct" mode rgb value.
static u32
get_color(int depth, u8 attr)
{
int rbits, gbits, bbits;
switch (depth) {
case 15: rbits=5; gbits=5; bbits=5; break;
case 16: rbits=5; gbits=6; bbits=5; break;
default:
case 24: rbits=8; gbits=8; bbits=8; break;
}
int h = (attr&8) ? 1 : 0;
int r = (attr&4) ? 2 : 0, g = (attr&2) ? 2 : 0, b = (attr&1) ? 2 : 0;
if ((attr & 0xf) == 6)
g = 1;
int rv = DIV_ROUND_CLOSEST(((1<<rbits) - 1) * (r + h), 3);
int gv = DIV_ROUND_CLOSEST(((1<<gbits) - 1) * (g + h), 3);
int bv = DIV_ROUND_CLOSEST(((1<<bbits) - 1) * (b + h), 3);
return (rv << (gbits+bbits)) + (gv << bbits) + bv;
}
// Find the closest attribute for a given framebuffer color
static u8
reverse_color(int depth, u32 color)
{
int rbits, gbits, bbits;
switch (depth) {
case 15: rbits=5; gbits=5; bbits=5; break;
case 16: rbits=5; gbits=6; bbits=5; break;
default:
case 24: rbits=8; gbits=8; bbits=8; break;
}
int rv = (color >> (gbits+bbits)) & ((1<<rbits)-1);
int gv = (color >> bbits) & ((1<<gbits)-1);
int bv = color & ((1<<bbits)-1);
int r = DIV_ROUND_CLOSEST(rv * 3, (1<<rbits) - 1);
int g = DIV_ROUND_CLOSEST(gv * 3, (1<<gbits) - 1);
int b = DIV_ROUND_CLOSEST(bv * 3, (1<<bbits) - 1);
int h = r && g && b && (r != 2 || g != 2 || b != 2);
return (h ? 8 : 0) | ((r-h) ? 4 : 0) | ((g-h) ? 2 : 0) | ((b-h) ? 1 : 0);
}
static void
gfx_direct(struct gfx_op *op)
{
void *fb = (void*)GET_GLOBAL(VBE_framebuffer);
if (!fb)
return;
int depth = GET_GLOBAL(op->curmode_g->depth);
int bypp = DIV_ROUND_UP(depth, 8);
void *dest_far = (fb + op->displaystart + op->y * op->linelength
+ op->x * bypp);
u8 data[64];
int i;
switch (op->op) {
default:
case GO_READ8:
memcpy_high(MAKE_FLATPTR(GET_SEG(SS), data), dest_far, bypp * 8);
for (i=0; i<8; i++)
op->pixels[i] = reverse_color(depth, *(u32*)&data[i*bypp]);
break;
case GO_WRITE8:
for (i=0; i<8; i++)
*(u32*)&data[i*bypp] = get_color(depth, op->pixels[i]);
memcpy_high(dest_far, MAKE_FLATPTR(GET_SEG(SS), data), bypp * 8);
break;
case GO_MEMSET: ;
u32 color = get_color(depth, op->pixels[0]);
for (i=0; i<8; i++)
*(u32*)&data[i*bypp] = color;
memcpy_high(dest_far, MAKE_FLATPTR(GET_SEG(SS), data), bypp * 8);
memcpy_high(dest_far + bypp * 8, dest_far, op->xlen * bypp - bypp * 8);
for (i=1; i < op->ylen; i++)
memcpy_high(dest_far + op->linelength * i
, dest_far, op->xlen * bypp);
break;
case GO_MEMMOVE: ;
void *src_far = (fb + op->displaystart + op->srcy * op->linelength
+ op->x * bypp);
memmove_stride_high(dest_far, src_far
, op->xlen * bypp, op->linelength, op->ylen);
break;
}
}
/****************************************************************
* Gfx interface
****************************************************************/
// Prepare a struct gfx_op for use.
void
init_gfx_op(struct gfx_op *op, struct vgamode_s *curmode_g)
{
memset(op, 0, sizeof(*op));
op->curmode_g = curmode_g;
op->linelength = vgahw_get_linelength(curmode_g);
op->displaystart = vgahw_get_displaystart(curmode_g);
}
// Issue a graphics operation.
void
handle_gfx_op(struct gfx_op *op)
{
switch (GET_GLOBAL(op->curmode_g->memmodel)) {
case MM_PLANAR:
gfx_planar(op);
break;
case MM_CGA:
gfx_cga(op);
break;
case MM_PACKED:
gfx_packed(op);
break;
case MM_DIRECT:
gfx_direct(op);
break;
default:
break;
}
}
// Move characters when in graphics mode.
static void
gfx_move_chars(struct vgamode_s *curmode_g, struct cursorpos dest
, struct cursorpos movesize, int lines)
{
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.x = dest.x * 8;
op.xlen = movesize.x * 8;
int cheight = GET_BDA(char_height);
op.y = dest.y * cheight;
op.ylen = movesize.y * cheight;
op.srcy = op.y + lines * cheight;
op.op = GO_MEMMOVE;
handle_gfx_op(&op);
}
// Clear area of screen in graphics mode.
static void
gfx_clear_chars(struct vgamode_s *curmode_g, struct cursorpos win
, struct cursorpos winsize, struct carattr ca)
{
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.x = win.x * 8;
op.xlen = winsize.x * 8;
int cheight = GET_BDA(char_height);
op.y = win.y * cheight;
op.ylen = winsize.y * cheight;
op.pixels[0] = ca.attr;
if (vga_emulate_text())
op.pixels[0] = ca.attr >> 4;
op.op = GO_MEMSET;
handle_gfx_op(&op);
}
// Return the font for a given character
struct segoff_s
get_font_data(u8 c)
{
int char_height = GET_BDA(char_height);
struct segoff_s font;
if (char_height == 8 && c >= 128) {
font = GET_IVT(0x1f);
c -= 128;
} else {
font = GET_IVT(0x43);
}
font.offset += c * char_height;
return font;
}
// Write a character to the screen in graphics mode.
static void
gfx_write_char(struct vgamode_s *curmode_g
, struct cursorpos cp, struct carattr ca)
{
if (cp.x >= GET_BDA(video_cols))
return;
struct segoff_s font = get_font_data(ca.car);
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.x = cp.x * 8;
int cheight = GET_BDA(char_height);
op.y = cp.y * cheight;
u8 fgattr = ca.attr, bgattr = 0x00;
int usexor = 0;
if (vga_emulate_text()) {
if (ca.use_attr) {
bgattr = fgattr >> 4;
fgattr = fgattr & 0x0f;
} else {
// Read bottom right pixel of the cell to guess bg color
op.op = GO_READ8;
op.y += cheight-1;
handle_gfx_op(&op);
op.y -= cheight-1;
bgattr = op.pixels[7];
fgattr = bgattr ^ 0x7;
}
} else if (fgattr & 0x80 && GET_GLOBAL(curmode_g->depth) < 8) {
usexor = 1;
fgattr &= 0x7f;
}
int i;
for (i = 0; i < cheight; i++, op.y++) {
u8 fontline = GET_FARVAR(font.seg, *(u8*)(font.offset+i));
if (usexor) {
op.op = GO_READ8;
handle_gfx_op(&op);
int j;
for (j = 0; j < 8; j++)
op.pixels[j] ^= (fontline & (0x80>>j)) ? fgattr : 0x00;
} else {
int j;
for (j = 0; j < 8; j++)
op.pixels[j] = (fontline & (0x80>>j)) ? fgattr : bgattr;
}
op.op = GO_WRITE8;
handle_gfx_op(&op);
}
}
// Read a character from the screen in graphics mode.
static struct carattr
gfx_read_char(struct vgamode_s *curmode_g, struct cursorpos cp)
{
u8 lines[16];
int cheight = GET_BDA(char_height);
if (cp.x >= GET_BDA(video_cols) || cheight > ARRAY_SIZE(lines))
goto fail;
// Read cell from screen
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.op = GO_READ8;
op.x = cp.x * 8;
op.y = cp.y * cheight;
int car = 0;
u8 fgattr = 0x00, bgattr = 0x00;
if (vga_emulate_text()) {
// Read bottom right pixel of the cell to guess bg color
op.y += cheight-1;
handle_gfx_op(&op);
op.y -= cheight-1;
bgattr = op.pixels[7];
fgattr = bgattr ^ 0x7;
// Report space character for blank cells (skip null character check)
car = 1;
}
u8 i, j;
for (i=0; i<cheight; i++, op.y++) {
u8 line = 0;
handle_gfx_op(&op);
for (j=0; j<8; j++)
if (op.pixels[j] != bgattr) {
line |= 0x80 >> j;
fgattr = op.pixels[j];
}
lines[i] = line;
}
// Determine font
for (; car<256; car++) {
struct segoff_s font = get_font_data(car);
if (memcmp_far(GET_SEG(SS), lines
, font.seg, (void*)(font.offset+0), cheight) == 0)
return (struct carattr){car, fgattr | (bgattr << 4), 0};
}
fail:
return (struct carattr){0, 0, 0};
}
// Set the pixel at the given position.
void
vgafb_write_pixel(u8 color, u16 x, u16 y)
{
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return;
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.x = ALIGN_DOWN(x, 8);
op.y = y;
op.op = GO_READ8;
handle_gfx_op(&op);
int usexor = color & 0x80 && GET_GLOBAL(curmode_g->depth) < 8;
if (usexor)
op.pixels[x & 0x07] ^= color & 0x7f;
else
op.pixels[x & 0x07] = color;
op.op = GO_WRITE8;
handle_gfx_op(&op);
}
// Return the pixel at the given position.
u8
vgafb_read_pixel(u16 x, u16 y)
{
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return 0;
struct gfx_op op;
init_gfx_op(&op, curmode_g);
op.x = ALIGN_DOWN(x, 8);
op.y = y;
op.op = GO_READ8;
handle_gfx_op(&op);
return op.pixels[x & 0x07];
}
/****************************************************************
* Text ops
****************************************************************/
// Return the fb offset for the given character address when in text mode.
void *
text_address(struct cursorpos cp)
{
int stride = GET_BDA(video_cols) * 2;
u32 pageoffset = GET_BDA(video_pagesize) * cp.page;
return (void*)pageoffset + cp.y * stride + cp.x * 2;
}
// Move characters on screen.
static void
vgafb_move_chars(struct cursorpos dest, struct cursorpos movesize, int lines)
{
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return;
if (GET_GLOBAL(curmode_g->memmodel) != MM_TEXT) {
gfx_move_chars(curmode_g, dest, movesize, lines);
return;
}
int stride = GET_BDA(video_cols) * 2;
void *dest_addr = text_address(dest), *src_addr = dest_addr + lines * stride;
memmove_stride(GET_GLOBAL(curmode_g->sstart), dest_addr, src_addr
, movesize.x * 2, stride, movesize.y);
}
// Clear area of screen.
static void
vgafb_clear_chars(struct cursorpos win, struct cursorpos winsize
, struct carattr ca)
{
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return;
if (GET_GLOBAL(curmode_g->memmodel) != MM_TEXT) {
gfx_clear_chars(curmode_g, win, winsize, ca);
return;
}
int stride = GET_BDA(video_cols) * 2;
u16 attr = ((ca.use_attr ? ca.attr : 0x07) << 8) | ca.car;
memset16_stride(GET_GLOBAL(curmode_g->sstart), text_address(win), attr
, winsize.x * 2, stride, winsize.y);
}
// Scroll characters within a window on the screen
void
vgafb_scroll(struct cursorpos win, struct cursorpos winsize
, int lines, struct carattr ca)
{
if (!lines) {
// Clear window
vgafb_clear_chars(win, winsize, ca);
} else if (lines > 0) {
// Scroll the window up (eg, from page down key)
winsize.y -= lines;
vgafb_move_chars(win, winsize, lines);
win.y += winsize.y;
winsize.y = lines;
vgafb_clear_chars(win, winsize, ca);
} else {
// Scroll the window down (eg, from page up key)
win.y -= lines;
winsize.y += lines;
vgafb_move_chars(win, winsize, lines);
win.y += lines;
winsize.y = -lines;
vgafb_clear_chars(win, winsize, ca);
}
}
// Write a character to the screen.
void
vgafb_write_char(struct cursorpos cp, struct carattr ca)
{
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return;
if (GET_GLOBAL(curmode_g->memmodel) != MM_TEXT) {
gfx_write_char(curmode_g, cp, ca);
return;
}
void *dest_far = text_address(cp);
if (ca.use_attr) {
u16 dummy = (ca.attr << 8) | ca.car;
SET_FARVAR(GET_GLOBAL(curmode_g->sstart), *(u16*)dest_far, dummy);
} else {
SET_FARVAR(GET_GLOBAL(curmode_g->sstart), *(u8*)dest_far, ca.car);
}
}
// Return the character at the given position on the screen.
struct carattr
vgafb_read_char(struct cursorpos cp)
{
struct vgamode_s *curmode_g = get_current_mode();
if (!curmode_g)
return (struct carattr){0, 0, 0};
if (GET_GLOBAL(curmode_g->memmodel) != MM_TEXT)
return gfx_read_char(curmode_g, cp);
u16 *dest_far = text_address(cp);
u16 v = GET_FARVAR(GET_GLOBAL(curmode_g->sstart), *dest_far);
return (struct carattr){v, v>>8, 0};
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef __VGAFB_H
#define __VGAFB_H
// Graphics pixel operations.
struct gfx_op {
struct vgamode_s *curmode_g;
u32 linelength;
u32 displaystart;
u8 op;
u16 x, y;
u8 pixels[8];
u16 xlen, ylen;
u16 srcy;
};
#define GO_READ8 1
#define GO_WRITE8 2
#define GO_MEMSET 3
#define GO_MEMMOVE 4
struct cursorpos {
u8 x, y, page, pad;
};
struct carattr {
u8 car, attr, use_attr, pad;
};
// vgafb.c
void memcpy_high(void *dest, void *src, u32 len);
void init_gfx_op(struct gfx_op *op, struct vgamode_s *curmode_g);
void handle_gfx_op(struct gfx_op *op);
void *text_address(struct cursorpos cp);
void vgafb_scroll(struct cursorpos win, struct cursorpos winsize
, int lines, struct carattr ca);
void vgafb_write_char(struct cursorpos cp, struct carattr ca);
struct carattr vgafb_read_char(struct cursorpos cp);
void vgafb_write_pixel(u8 color, u16 x, u16 y);
u8 vgafb_read_pixel(u16 x, u16 y);
#endif // vgafb.h
+785
View File
@@ -0,0 +1,785 @@
#include "vgautil.h" // vgafont8
/*
* These fonts come from ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
* The package is (c) by Joseph Gil
* The individual fonts are public domain
*/
u8 vgafont8[256 * 8] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00,
0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78,
0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00,
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38,
0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00,
0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00,
0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00,
0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00,
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18,
0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00,
0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30,
0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7,
0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
u8 vgafont14[256 * 14] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
0x00, 0xc6, 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00,
0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x40, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00,
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
u8 vgafont16[256 * 16] VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
u8 vgafont14alt[1] VAR16;
u8 vgafont16alt[1] VAR16;
+160
View File
@@ -0,0 +1,160 @@
#ifndef __VGAHW_H
#define __VGAHW_H
#include "types.h" // u8
#include "config.h" // CONFIG_*
#include "bochsvga.h" // bochsvga_set_mode
#include "stdvga.h" // stdvga_set_mode
#include "geodevga.h" // geodevga_setup
#include "vgautil.h" // stdvga_list_modes
static inline struct vgamode_s *vgahw_find_mode(int mode) {
if (CONFIG_VGA_CIRRUS)
return clext_find_mode(mode);
if (CONFIG_VGA_ATI)
return ati_find_mode(mode);
if (CONFIG_VGA_BOCHS)
return bochsvga_find_mode(mode);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_find_mode(mode);
return stdvga_find_mode(mode);
}
static inline int vgahw_set_mode(struct vgamode_s *vmode_g, int flags) {
if (CONFIG_VGA_CIRRUS)
return clext_set_mode(vmode_g, flags);
if (CONFIG_VGA_ATI)
return ati_set_mode(vmode_g, flags);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_mode(vmode_g, flags);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_mode(vmode_g, flags);
return stdvga_set_mode(vmode_g, flags);
}
static inline void vgahw_list_modes(u16 seg, u16 *dest, u16 *last) {
if (CONFIG_VGA_CIRRUS)
clext_list_modes(seg, dest, last);
else if (CONFIG_VGA_ATI)
ati_list_modes(seg, dest, last);
else if (CONFIG_VGA_BOCHS)
bochsvga_list_modes(seg, dest, last);
else if (CONFIG_VGA_EMULATE_TEXT)
cbvga_list_modes(seg, dest, last);
else
stdvga_list_modes(seg, dest, last);
}
static inline int vgahw_setup(void) {
if (CONFIG_VGA_CIRRUS)
return clext_setup();
if (CONFIG_VGA_ATI)
return ati_setup();
if (CONFIG_VGA_BOCHS)
return bochsvga_setup();
if (CONFIG_VGA_GEODEGX2 || CONFIG_VGA_GEODELX)
return geodevga_setup();
if (CONFIG_VGA_COREBOOT)
return cbvga_setup();
if (CONFIG_DISPLAY_BOCHS)
return bochs_display_setup();
if (CONFIG_VGA_RAMFB)
return ramfb_setup();
return stdvga_setup();
}
static inline int vgahw_get_window(struct vgamode_s *curmode_g, int window) {
if (CONFIG_VGA_CIRRUS)
return clext_get_window(curmode_g, window);
if (CONFIG_VGA_BOCHS)
return bochsvga_get_window(curmode_g, window);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_window(curmode_g, window);
return stdvga_get_window(curmode_g, window);
}
static inline int vgahw_set_window(struct vgamode_s *curmode_g, int window
, int val) {
if (CONFIG_VGA_CIRRUS)
return clext_set_window(curmode_g, window, val);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_window(curmode_g, window, val);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_window(curmode_g, window, val);
return stdvga_set_window(curmode_g, window, val);
}
static inline int vgahw_get_linelength(struct vgamode_s *curmode_g) {
if (CONFIG_VGA_CIRRUS)
return clext_get_linelength(curmode_g);
if (CONFIG_VGA_BOCHS)
return bochsvga_get_linelength(curmode_g);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_linelength(curmode_g);
return stdvga_get_linelength(curmode_g);
}
static inline int vgahw_minimum_linelength(struct vgamode_s *vmode_g) {
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_minimum_linelength(vmode_g);
return stdvga_minimum_linelength(vmode_g);
}
static inline int vgahw_set_linelength(struct vgamode_s *curmode_g, int val) {
if (CONFIG_VGA_CIRRUS)
return clext_set_linelength(curmode_g, val);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_linelength(curmode_g, val);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_linelength(curmode_g, val);
return stdvga_set_linelength(curmode_g, val);
}
static inline int vgahw_get_displaystart(struct vgamode_s *curmode_g) {
if (CONFIG_VGA_CIRRUS)
return clext_get_displaystart(curmode_g);
if (CONFIG_VGA_BOCHS)
return bochsvga_get_displaystart(curmode_g);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_displaystart(curmode_g);
return stdvga_get_displaystart(curmode_g);
}
static inline int vgahw_set_displaystart(struct vgamode_s *curmode_g, int val) {
if (CONFIG_VGA_CIRRUS)
return clext_set_displaystart(curmode_g, val);
if (CONFIG_VGA_BOCHS)
return bochsvga_set_displaystart(curmode_g, val);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_displaystart(curmode_g, val);
return stdvga_set_displaystart(curmode_g, val);
}
static inline int vgahw_get_dacformat(struct vgamode_s *curmode_g) {
if (CONFIG_VGA_BOCHS)
return bochsvga_get_dacformat(curmode_g);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_get_dacformat(curmode_g);
return stdvga_get_dacformat(curmode_g);
}
static inline int vgahw_set_dacformat(struct vgamode_s *curmode_g, int val) {
if (CONFIG_VGA_BOCHS)
return bochsvga_set_dacformat(curmode_g, val);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_set_dacformat(curmode_g, val);
return stdvga_set_dacformat(curmode_g, val);
}
static inline int vgahw_save_restore(int cmd, u16 seg, void *data) {
if (CONFIG_VGA_CIRRUS)
return clext_save_restore(cmd, seg, data);
if (CONFIG_VGA_BOCHS)
return bochsvga_save_restore(cmd, seg, data);
if (CONFIG_VGA_EMULATE_TEXT)
return cbvga_save_restore(cmd, seg, data);
return stdvga_save_restore(cmd, seg, data);
}
#endif // vgahw.h
+202
View File
@@ -0,0 +1,202 @@
// Main VGA bios initialization
//
// Copyright (C) 2009-2013 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 "biosvar.h" // SET_BDA
#include "bregs.h" // struct bregs
#include "hw/pci.h" // pci_config_readw
#include "hw/pci_regs.h" // PCI_VENDOR_ID
#include "hw/serialio.h" // serial_debug_preinit
#include "output.h" // dprintf
#include "std/optionrom.h" // struct pci_data
#include "std/pmm.h" // struct pmmheader
#include "string.h" // checksum_far
#include "vgabios.h" // SET_VGA
#include "vgahw.h" // vgahw_setup
#include "vgautil.h" // swcursor_check_event
// Type of emulator platform - for dprintf with certain compile options.
int PlatformRunningOn VAR16;
/****************************************************************
* PCI Data
****************************************************************/
struct pci_data rom_pci_data VAR16 VISIBLE16 = {
.signature = PCI_ROM_SIGNATURE,
.vendor = CONFIG_VGA_VID,
.device = CONFIG_VGA_DID,
.dlen = 0x18,
.class_hi = 0x300,
.irevision = 1,
.type = PCIROM_CODETYPE_X86,
.indicator = 0x80,
};
/****************************************************************
* PMM call and extra stack setup
****************************************************************/
u32
allocate_pmm(u32 size, int highmem, int aligned)
{
u32 pmmscan;
for (pmmscan=0; pmmscan < BUILD_BIOS_SIZE; pmmscan+=16) {
struct pmmheader *pmm = (void*)pmmscan;
if (GET_FARVAR(SEG_BIOS, pmm->signature) != PMM_SIGNATURE)
continue;
if (checksum_far(SEG_BIOS, pmm, GET_FARVAR(SEG_BIOS, pmm->length)))
continue;
struct segoff_s entry = GET_FARVAR(SEG_BIOS, pmm->entry);
dprintf(1, "Attempting to allocate %u bytes %s via pmm call to %04x:%04x\n"
, size, highmem ? "highmem" : "lowmem"
, entry.seg, entry.offset);
u16 res1, res2;
u16 flags = 8 |
( highmem ? 2 : 1 )|
( aligned ? 4 : 0 );
size >>= 4;
asm volatile(
"pushl %0\n"
"pushw %2\n" // flags
"pushl $0xffffffff\n" // Anonymous handle
"pushl %1\n" // size
"pushw $0x00\n" // PMM allocation request
"lcallw *12(%%esp)\n"
"addl $16, %%esp\n"
"cli\n"
"cld\n"
: "+r" (entry.segoff), "+r" (size), "+r" (flags),
"=a" (res1), "=d" (res2) : : "cc", "memory");
u32 res = res1 | (res2 << 16);
if (!res || res == PMM_FUNCTION_NOT_SUPPORTED)
return 0;
return res;
}
return 0;
}
u16 ExtraStackSeg VAR16 VISIBLE16;
static void
allocate_extra_stack(void)
{
if (!CONFIG_VGA_ALLOCATE_EXTRA_STACK)
return;
u32 res = allocate_pmm(CONFIG_VGA_EXTRA_STACK_SIZE, 0, 0);
if (!res)
return;
dprintf(1, "VGA stack allocated at %x\n", res);
SET_VGA(ExtraStackSeg, res >> 4);
extern void entry_10_extrastack(void);
SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10_extrastack));
return;
}
/****************************************************************
* Timer hook
****************************************************************/
struct segoff_s Timer_Hook_Resume VAR16 VISIBLE16;
void VISIBLE16
handle_timer_hook(void)
{
swcursor_check_event();
}
static void
hook_timer_irq(void)
{
if (!CONFIG_VGA_EMULATE_TEXT)
return;
extern void entry_timer_hook(void);
extern void entry_timer_hook_extrastack(void);
struct segoff_s oldirq = GET_IVT(0x08);
struct segoff_s newirq = SEGOFF(get_global_seg(), (u32)entry_timer_hook);
if (CONFIG_VGA_ALLOCATE_EXTRA_STACK && GET_GLOBAL(ExtraStackSeg))
newirq = SEGOFF(get_global_seg(), (u32)entry_timer_hook_extrastack);
dprintf(1, "Hooking hardware timer irq (old=%x new=%x)\n"
, oldirq.segoff, newirq.segoff);
SET_VGA(Timer_Hook_Resume, oldirq);
SET_IVT(0x08, newirq);
}
/****************************************************************
* VGA post
****************************************************************/
static void
init_bios_area(void)
{
// init detected hardware BIOS Area
// set 80x25 color (not clear from RBIL but usual)
set_equipment_flags(0x30, 0x20);
// Set the basic modeset options
SET_BDA(modeset_ctl, 0x51);
SET_BDA(dcc_index, CONFIG_VGA_STDVGA_PORTS ? 0x08 : 0xff);
// FIXME
SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
}
int VgaBDF VAR16 = -1;
int HaveRunInit VAR16;
void VISIBLE16
vga_post(struct bregs *regs)
{
serial_debug_preinit();
dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION);
dprintf(1, "VGABUILD: %s\n", BUILDINFO);
debug_enter(regs, DEBUG_VGA_POST);
if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) {
u16 bdf = regs->ax;
if ((pci_config_readw(bdf, PCI_VENDOR_ID)
== GET_GLOBAL(rom_pci_data.vendor))
&& (pci_config_readw(bdf, PCI_DEVICE_ID)
== GET_GLOBAL(rom_pci_data.device)))
SET_VGA(VgaBDF, bdf);
}
int ret = vgahw_setup();
if (ret) {
dprintf(1, "Failed to initialize VGA hardware. Exiting.\n");
return;
}
if (GET_GLOBAL(HaveRunInit))
return;
init_bios_area();
if (CONFIG_VGA_STDVGA_PORTS)
stdvga_build_video_param();
extern void entry_10(void);
SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
allocate_extra_stack();
hook_timer_irq();
SET_VGA(HaveRunInit, 1);
// Fixup checksum
extern u8 _rom_header_size, _rom_header_checksum;
SET_VGA(_rom_header_checksum, 0);
u8 sum = -checksum_far(get_global_seg(), 0,
GET_GLOBAL(_rom_header_size) * 512);
SET_VGA(_rom_header_checksum, sum);
}
+30
View File
@@ -0,0 +1,30 @@
// Linker definitions for an option rom
//
// Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH("i386")
ENTRY(_optionrom_entry)
SECTIONS
{
.text 0 : {
KEEP(*(.rom.header))
*(.text.*)
_rodata = . ;
*(.rodata*)
*(.data16.*)
}
// Discard regular data sections to force a link error if
// 16bit code attempts to access data not marked with VAR16.
/DISCARD/ : {
*(.text*)
*(.rodata*)
*(.data*)
*(.bss*)
*(COMMON)
*(.note*)
}
}
+86
View File
@@ -0,0 +1,86 @@
// Misc function and variable declarations.
#ifndef __VGAUTIL_H
#define __VGAUTIL_H
#include "types.h" // u8
// cbvga.c
struct vgamode_s *cbvga_find_mode(int mode);
void cbvga_list_modes(u16 seg, u16 *dest, u16 *last);
int cbvga_get_window(struct vgamode_s *curmode_g, int window);
int cbvga_set_window(struct vgamode_s *curmode_g, int window, int val);
int cbvga_minimum_linelength(struct vgamode_s *vmode_g);
int cbvga_get_linelength(struct vgamode_s *curmode_g);
int cbvga_set_linelength(struct vgamode_s *curmode_g, int val);
int cbvga_get_displaystart(struct vgamode_s *curmode_g);
int cbvga_set_displaystart(struct vgamode_s *curmode_g, int val);
int cbvga_get_dacformat(struct vgamode_s *curmode_g);
int cbvga_set_dacformat(struct vgamode_s *curmode_g, int val);
int cbvga_save_restore(int cmd, u16 seg, void *data);
int cbvga_set_mode(struct vgamode_s *vmode_g, int flags);
void cbvga_setup_modes(u64 addr, u8 bpp, u32 xlines, u32 ylines, u32 linelength);
int cbvga_setup(void);
// bochsdisplay.c
int bochs_display_setup(void);
// ramfb.c
int ramfb_setup(void);
// clext.c
struct vgamode_s *clext_find_mode(int mode);
void clext_list_modes(u16 seg, u16 *dest, u16 *last);
int clext_get_window(struct vgamode_s *curmode_g, int window);
int clext_set_window(struct vgamode_s *curmode_g, int window, int val);
int clext_get_linelength(struct vgamode_s *curmode_g);
int clext_set_linelength(struct vgamode_s *curmode_g, int val);
int clext_get_displaystart(struct vgamode_s *curmode_g);
int clext_set_displaystart(struct vgamode_s *curmode_g, int val);
int clext_save_restore(int cmd, u16 seg, void *data);
int clext_set_mode(struct vgamode_s *vmode_g, int flags);
struct bregs;
void clext_1012(struct bregs *regs);
int clext_setup(void);
// atiext.c
struct vgamode_s *ati_find_mode(int mode);
void ati_list_modes(u16 seg, u16 *dest, u16 *last);
int ati_set_mode(struct vgamode_s *vmode_g, int flags);
int ati_setup(void);
// stdvgamodes.c
struct vgamode_s *stdvga_find_mode(int mode);
void stdvga_list_modes(u16 seg, u16 *dest, u16 *last);
void stdvga_build_video_param(void);
void stdvga_override_crtc(int mode, u8 *crtc);
int stdvga_set_mode(struct vgamode_s *vmode_g, int flags);
void stdvga_set_packed_palette(void);
// swcursor.c
void swcursor_pre_handle10(struct bregs *regs);
void swcursor_check_event(void);
// vbe.c
extern u32 VBE_total_memory;
extern u32 VBE_capabilities;
extern u32 VBE_framebuffer;
extern u16 VBE_win_granularity;
extern u8 VBE_edid[256];
void handle_104f(struct bregs *regs);
// vgafonts.c
extern u8 vgafont8[];
extern u8 vgafont14[];
extern u8 vgafont16[];
extern u8 vgafont14alt[];
extern u8 vgafont16alt[];
// vgainit.c
extern int VgaBDF;
extern int HaveRunInit;
u32 allocate_pmm(u32 size, int highmem, int aligned);
// vgaversion.c
extern const char VERSION[], BUILDINFO[];
#endif // vgautil.h
+6
View File
@@ -0,0 +1,6 @@
// Place build generated version into a C variable
#include "autovgaversion.h"
#include "types.h"
char VERSION[] VAR16 = BUILD_VERSION;
char BUILDINFO[] VAR16 = BUILD_TOOLS;