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