blob: d164cf5c96c60ccb7d66144c65140944c2c0b26b [file] [log] [blame]
#include "kvm/bios.h"
#include "kvm/vesa.h"
#include "asm/bios/memcpy.h"
#include "asm/bios/vesa.h"
static far_ptr gen_far_ptr(unsigned int pa)
{
far_ptr ptr;
ptr.seg = (pa >> 4);
ptr.off = pa - (ptr.seg << 4);
return ptr;
}
static inline void outb(unsigned short port, unsigned char val)
{
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
/*
* It's probably much more useful to make this print to the serial
* line rather than print to a non-displayed VGA memory
*/
static inline void int10_putchar(struct biosregs *args)
{
u8 al = args->eax & 0xFF;
outb(0x3f8, al);
}
static void vbe_get_mode(struct biosregs *args)
{
struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi;
*info = (struct vesa_mode_info) {
.mode_attr = 0xd9, /* 11011011 */
.logical_scan = VESA_WIDTH*4,
.h_res = VESA_WIDTH,
.v_res = VESA_HEIGHT,
.bpp = VESA_BPP,
.memory_layout = 6,
.memory_planes = 1,
.lfb_ptr = VESA_MEM_ADDR,
.rmask = 8,
.gmask = 8,
.bmask = 8,
.resv_mask = 8,
.resv_pos = 24,
.bpos = 16,
.gpos = 8,
};
}
static void vbe_get_info(struct biosregs *args)
{
struct vesa_general_info *infop = (struct vesa_general_info *) args->edi;
struct vesa_general_info info;
info = (struct vesa_general_info) {
.signature = VESA_MAGIC,
.version = 0x102,
.vendor_string = gen_far_ptr(VGA_ROM_BEGIN),
.capabilities = 0x10,
.video_mode_ptr = gen_far_ptr(VGA_ROM_MODES),
.total_memory = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
};
memcpy16(args->es, infop, args->ds, &info, sizeof(info));
}
#define VBE_STATUS_OK 0x004F
static void int10_vesa(struct biosregs *args)
{
u8 al;
al = args->eax & 0xff;
switch (al) {
case 0x00:
vbe_get_info(args);
break;
case 0x01:
vbe_get_mode(args);
break;
}
args->eax = VBE_STATUS_OK;
}
bioscall void int10_handler(struct biosregs *args)
{
u8 ah;
ah = (args->eax & 0xff00) >> 8;
switch (ah) {
case 0x0e:
int10_putchar(args);
break;
case 0x4f:
int10_vesa(args);
break;
}
}