1cc8875d1SJohn Floren #include "kvm/bios.h"
2cc8875d1SJohn Floren #include "kvm/vesa.h"
3b4eab05eSPekka Enberg
4*9759db0dSAndre Przywara #include "asm/bios/memcpy.h"
5b4eab05eSPekka Enberg
623323929SAndre Przywara #include "asm/bios/vesa.h"
7cc8875d1SJohn Floren
gen_far_ptr(unsigned int pa)855290abcSCyrill Gorcunov static far_ptr gen_far_ptr(unsigned int pa)
955290abcSCyrill Gorcunov {
1055290abcSCyrill Gorcunov far_ptr ptr;
11cc8875d1SJohn Floren
1255290abcSCyrill Gorcunov ptr.seg = (pa >> 4);
1355290abcSCyrill Gorcunov ptr.off = pa - (ptr.seg << 4);
14cc8875d1SJohn Floren
1555290abcSCyrill Gorcunov return ptr;
1655290abcSCyrill Gorcunov }
17cc8875d1SJohn Floren
outb(unsigned short port,unsigned char val)18cc8875d1SJohn Floren static inline void outb(unsigned short port, unsigned char val)
19cc8875d1SJohn Floren {
20cc8875d1SJohn Floren asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
21cc8875d1SJohn Floren }
22cc8875d1SJohn Floren
23cc8875d1SJohn Floren /*
24cc8875d1SJohn Floren * It's probably much more useful to make this print to the serial
25cc8875d1SJohn Floren * line rather than print to a non-displayed VGA memory
26cc8875d1SJohn Floren */
int10_putchar(struct biosregs * args)27b97af2a3SPekka Enberg static inline void int10_putchar(struct biosregs *args)
28cc8875d1SJohn Floren {
2986a36524SCyrill Gorcunov u8 al = args->eax & 0xFF;
30cc8875d1SJohn Floren
31cc8875d1SJohn Floren outb(0x3f8, al);
32cc8875d1SJohn Floren }
33cc8875d1SJohn Floren
vbe_get_mode(struct biosregs * args)34b97af2a3SPekka Enberg static void vbe_get_mode(struct biosregs *args)
35cc8875d1SJohn Floren {
3655290abcSCyrill Gorcunov struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi;
37cc8875d1SJohn Floren
3855290abcSCyrill Gorcunov *info = (struct vesa_mode_info) {
39cc8875d1SJohn Floren .mode_attr = 0xd9, /* 11011011 */
40cc8875d1SJohn Floren .logical_scan = VESA_WIDTH*4,
41cc8875d1SJohn Floren .h_res = VESA_WIDTH,
42cc8875d1SJohn Floren .v_res = VESA_HEIGHT,
43cc8875d1SJohn Floren .bpp = VESA_BPP,
44cc8875d1SJohn Floren .memory_layout = 6,
45cc8875d1SJohn Floren .memory_planes = 1,
46cc8875d1SJohn Floren .lfb_ptr = VESA_MEM_ADDR,
47cc8875d1SJohn Floren .rmask = 8,
48cc8875d1SJohn Floren .gmask = 8,
49cc8875d1SJohn Floren .bmask = 8,
50cc8875d1SJohn Floren .resv_mask = 8,
51cc8875d1SJohn Floren .resv_pos = 24,
52cc8875d1SJohn Floren .bpos = 16,
53cc8875d1SJohn Floren .gpos = 8,
54cc8875d1SJohn Floren };
55d94966feSPekka Enberg }
56cc8875d1SJohn Floren
vbe_get_info(struct biosregs * args)57b97af2a3SPekka Enberg static void vbe_get_info(struct biosregs *args)
58d94966feSPekka Enberg {
59b4eab05eSPekka Enberg struct vesa_general_info *infop = (struct vesa_general_info *) args->edi;
60b4eab05eSPekka Enberg struct vesa_general_info info;
61d94966feSPekka Enberg
62b4eab05eSPekka Enberg info = (struct vesa_general_info) {
63d94966feSPekka Enberg .signature = VESA_MAGIC,
64d94966feSPekka Enberg .version = 0x102,
6555290abcSCyrill Gorcunov .vendor_string = gen_far_ptr(VGA_ROM_BEGIN),
66d94966feSPekka Enberg .capabilities = 0x10,
6755290abcSCyrill Gorcunov .video_mode_ptr = gen_far_ptr(VGA_ROM_MODES),
68d94966feSPekka Enberg .total_memory = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
69d94966feSPekka Enberg };
70b4eab05eSPekka Enberg
71b4eab05eSPekka Enberg memcpy16(args->es, infop, args->ds, &info, sizeof(info));
72d94966feSPekka Enberg }
73d94966feSPekka Enberg
74d94966feSPekka Enberg #define VBE_STATUS_OK 0x004F
75d94966feSPekka Enberg
int10_vesa(struct biosregs * args)76b97af2a3SPekka Enberg static void int10_vesa(struct biosregs *args)
77d94966feSPekka Enberg {
78d94966feSPekka Enberg u8 al;
79d94966feSPekka Enberg
8022c180cbSPekka Enberg al = args->eax & 0xff;
81d94966feSPekka Enberg
82d94966feSPekka Enberg switch (al) {
83d94966feSPekka Enberg case 0x00:
84d94966feSPekka Enberg vbe_get_info(args);
85d94966feSPekka Enberg break;
86d94966feSPekka Enberg case 0x01:
87d94966feSPekka Enberg vbe_get_mode(args);
88cc8875d1SJohn Floren break;
89cc8875d1SJohn Floren }
90cc8875d1SJohn Floren
91d94966feSPekka Enberg args->eax = VBE_STATUS_OK;
92cc8875d1SJohn Floren }
93cc8875d1SJohn Floren
int10_handler(struct biosregs * args)94b97af2a3SPekka Enberg bioscall void int10_handler(struct biosregs *args)
95cc8875d1SJohn Floren {
96cc8875d1SJohn Floren u8 ah;
97cc8875d1SJohn Floren
98cc8875d1SJohn Floren ah = (args->eax & 0xff00) >> 8;
99cc8875d1SJohn Floren
100cc8875d1SJohn Floren switch (ah) {
101cc8875d1SJohn Floren case 0x0e:
102cc8875d1SJohn Floren int10_putchar(args);
103cc8875d1SJohn Floren break;
104cc8875d1SJohn Floren case 0x4f:
105cc8875d1SJohn Floren int10_vesa(args);
106cc8875d1SJohn Floren break;
107cc8875d1SJohn Floren }
108cc8875d1SJohn Floren
109cc8875d1SJohn Floren }
110