xref: /kvmtool/x86/bios/int10.c (revision 9759db0dd916586ff022f5d16bde5ab52cc05e83)
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