xref: /kvmtool/x86/bios/int10.c (revision cc8875d1d2a40dce146a12446d30e67cda7b277a)
1*cc8875d1SJohn Floren #include "kvm/segment.h"
2*cc8875d1SJohn Floren #include "kvm/bios.h"
3*cc8875d1SJohn Floren #include "kvm/util.h"
4*cc8875d1SJohn Floren #include "kvm/vesa.h"
5*cc8875d1SJohn Floren #include <stdint.h>
6*cc8875d1SJohn Floren 
7*cc8875d1SJohn Floren #define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
8*cc8875d1SJohn Floren 
9*cc8875d1SJohn Floren struct int10_args {
10*cc8875d1SJohn Floren 	u32	eax;
11*cc8875d1SJohn Floren 	u32	ebx;
12*cc8875d1SJohn Floren 	u32	ecx;
13*cc8875d1SJohn Floren 	u32	edx;
14*cc8875d1SJohn Floren 	u32	esp;
15*cc8875d1SJohn Floren 	u32	ebp;
16*cc8875d1SJohn Floren 	u32	esi;
17*cc8875d1SJohn Floren 	u32	edi;
18*cc8875d1SJohn Floren 	u32	es;
19*cc8875d1SJohn Floren };
20*cc8875d1SJohn Floren 
21*cc8875d1SJohn Floren /* VESA General Information table */
22*cc8875d1SJohn Floren struct vesa_general_info {
23*cc8875d1SJohn Floren 	u32 signature;			/* 0 Magic number = "VESA" */
24*cc8875d1SJohn Floren 	u16 version;			/* 4 */
25*cc8875d1SJohn Floren 	void *vendor_string;		/* 6 */
26*cc8875d1SJohn Floren 	u32 capabilities;		/* 10 */
27*cc8875d1SJohn Floren 	void *video_mode_ptr;		/* 14 */
28*cc8875d1SJohn Floren 	u16 total_memory;		/* 18 */
29*cc8875d1SJohn Floren 
30*cc8875d1SJohn Floren 	u8 reserved[236];		/* 20 */
31*cc8875d1SJohn Floren } __attribute__ ((packed));
32*cc8875d1SJohn Floren 
33*cc8875d1SJohn Floren 
34*cc8875d1SJohn Floren struct vminfo {
35*cc8875d1SJohn Floren 	u16	mode_attr;		/* 0 */
36*cc8875d1SJohn Floren 	u8	win_attr[2];		/* 2 */
37*cc8875d1SJohn Floren 	u16	win_grain;		/* 4 */
38*cc8875d1SJohn Floren 	u16	win_size;		/* 6 */
39*cc8875d1SJohn Floren 	u16	win_seg[2];		/* 8 */
40*cc8875d1SJohn Floren 	u32	win_scheme;		/* 12 */
41*cc8875d1SJohn Floren 	u16	logical_scan;		/* 16 */
42*cc8875d1SJohn Floren 
43*cc8875d1SJohn Floren 	u16	h_res;			/* 18 */
44*cc8875d1SJohn Floren 	u16	v_res;			/* 20 */
45*cc8875d1SJohn Floren 	u8	char_width;		/* 22 */
46*cc8875d1SJohn Floren 	u8	char_height;		/* 23 */
47*cc8875d1SJohn Floren 	u8	memory_planes;		/* 24 */
48*cc8875d1SJohn Floren 	u8	bpp;			/* 25 */
49*cc8875d1SJohn Floren 	u8	banks;			/* 26 */
50*cc8875d1SJohn Floren 	u8	memory_layout;		/* 27 */
51*cc8875d1SJohn Floren 	u8	bank_size;		/* 28 */
52*cc8875d1SJohn Floren 	u8	image_planes;		/* 29 */
53*cc8875d1SJohn Floren 	u8	page_function;		/* 30 */
54*cc8875d1SJohn Floren 
55*cc8875d1SJohn Floren 	u8	rmask;			/* 31 */
56*cc8875d1SJohn Floren 	u8	rpos;			/* 32 */
57*cc8875d1SJohn Floren 	u8	gmask;			/* 33 */
58*cc8875d1SJohn Floren 	u8	gpos;			/* 34 */
59*cc8875d1SJohn Floren 	u8	bmask;			/* 35 */
60*cc8875d1SJohn Floren 	u8	bpos;			/* 36 */
61*cc8875d1SJohn Floren 	u8	resv_mask;		/* 37 */
62*cc8875d1SJohn Floren 	u8	resv_pos;		/* 38 */
63*cc8875d1SJohn Floren 	u8	dcm_info;		/* 39 */
64*cc8875d1SJohn Floren 
65*cc8875d1SJohn Floren 	u32	lfb_ptr;		/* 40 Linear frame buffer address */
66*cc8875d1SJohn Floren 	u32	offscreen_ptr;		/* 44 Offscreen memory address */
67*cc8875d1SJohn Floren 	u16	offscreen_size;		/* 48 */
68*cc8875d1SJohn Floren 
69*cc8875d1SJohn Floren 	u8	reserved[206];		/* 50 */
70*cc8875d1SJohn Floren };
71*cc8875d1SJohn Floren 
72*cc8875d1SJohn Floren char oemstring[11] = "KVM VESA";
73*cc8875d1SJohn Floren u16 modes[2] = { 0x0112, 0xffff };
74*cc8875d1SJohn Floren 
75*cc8875d1SJohn Floren static inline void outb(unsigned short port, unsigned char val)
76*cc8875d1SJohn Floren {
77*cc8875d1SJohn Floren 	asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
78*cc8875d1SJohn Floren }
79*cc8875d1SJohn Floren 
80*cc8875d1SJohn Floren /*
81*cc8875d1SJohn Floren  * It's probably much more useful to make this print to the serial
82*cc8875d1SJohn Floren  * line rather than print to a non-displayed VGA memory
83*cc8875d1SJohn Floren  */
84*cc8875d1SJohn Floren static inline void int10_putchar(struct int10_args *args)
85*cc8875d1SJohn Floren {
86*cc8875d1SJohn Floren 	u8 al, ah;
87*cc8875d1SJohn Floren 
88*cc8875d1SJohn Floren 	al = args->eax & 0xFF;
89*cc8875d1SJohn Floren 	ah = (args->eax & 0xFF00) >> 8;
90*cc8875d1SJohn Floren 
91*cc8875d1SJohn Floren 	outb(0x3f8, al);
92*cc8875d1SJohn Floren }
93*cc8875d1SJohn Floren 
94*cc8875d1SJohn Floren static void int10_vesa(struct int10_args *args)
95*cc8875d1SJohn Floren {
96*cc8875d1SJohn Floren 	u8 al, ah;
97*cc8875d1SJohn Floren 	struct vesa_general_info *destination;
98*cc8875d1SJohn Floren 	struct vminfo *vi;
99*cc8875d1SJohn Floren 
100*cc8875d1SJohn Floren 	al = args->eax;
101*cc8875d1SJohn Floren 	ah = args->eax >> 8;
102*cc8875d1SJohn Floren 
103*cc8875d1SJohn Floren 	switch (al) {
104*cc8875d1SJohn Floren 	case 0:
105*cc8875d1SJohn Floren 		/* Set controller info */
106*cc8875d1SJohn Floren 
107*cc8875d1SJohn Floren 		destination = (struct vesa_general_info *)args->edi;
108*cc8875d1SJohn Floren 		*destination = (struct vesa_general_info) {
109*cc8875d1SJohn Floren 			.signature	= VESA_MAGIC,
110*cc8875d1SJohn Floren 			.version	= 0x102,
111*cc8875d1SJohn Floren 			.vendor_string	= oemstring,
112*cc8875d1SJohn Floren 			.capabilities	= 0x10,
113*cc8875d1SJohn Floren 			.video_mode_ptr	= modes,
114*cc8875d1SJohn Floren 			.total_memory	= (4*VESA_WIDTH * VESA_HEIGHT) / 0x10000,
115*cc8875d1SJohn Floren 		};
116*cc8875d1SJohn Floren 
117*cc8875d1SJohn Floren 		break;
118*cc8875d1SJohn Floren 	case 1:
119*cc8875d1SJohn Floren 		vi = (struct vminfo *)args->edi;
120*cc8875d1SJohn Floren 		*vi = (struct vminfo) {
121*cc8875d1SJohn Floren 			.mode_attr	= 0xd9, /* 11011011 */
122*cc8875d1SJohn Floren 			.logical_scan	= VESA_WIDTH*4,
123*cc8875d1SJohn Floren 			.h_res		= VESA_WIDTH,
124*cc8875d1SJohn Floren 			.v_res		= VESA_HEIGHT,
125*cc8875d1SJohn Floren 			.bpp		= VESA_BPP,
126*cc8875d1SJohn Floren 			.memory_layout	= 6,
127*cc8875d1SJohn Floren 			.memory_planes	= 1,
128*cc8875d1SJohn Floren 			.lfb_ptr	= VESA_MEM_ADDR,
129*cc8875d1SJohn Floren 			.rmask		= 8,
130*cc8875d1SJohn Floren 			.gmask		= 8,
131*cc8875d1SJohn Floren 			.bmask		= 8,
132*cc8875d1SJohn Floren 			.resv_mask	= 8,
133*cc8875d1SJohn Floren 			.resv_pos	= 24,
134*cc8875d1SJohn Floren 			.bpos		= 16,
135*cc8875d1SJohn Floren 			.gpos		= 8,
136*cc8875d1SJohn Floren 		};
137*cc8875d1SJohn Floren 
138*cc8875d1SJohn Floren 		break;
139*cc8875d1SJohn Floren 	}
140*cc8875d1SJohn Floren 
141*cc8875d1SJohn Floren 	args->eax			= 0x004f; /* return success every time */
142*cc8875d1SJohn Floren 
143*cc8875d1SJohn Floren }
144*cc8875d1SJohn Floren 
145*cc8875d1SJohn Floren bioscall void int10_handler(struct int10_args *args)
146*cc8875d1SJohn Floren {
147*cc8875d1SJohn Floren 	u8 ah;
148*cc8875d1SJohn Floren 
149*cc8875d1SJohn Floren 	ah = (args->eax & 0xff00) >> 8;
150*cc8875d1SJohn Floren 
151*cc8875d1SJohn Floren 	switch (ah) {
152*cc8875d1SJohn Floren 	case 0x0e:
153*cc8875d1SJohn Floren 		int10_putchar(args);
154*cc8875d1SJohn Floren 		break;
155*cc8875d1SJohn Floren 	case 0x4f:
156*cc8875d1SJohn Floren 		int10_vesa(args);
157*cc8875d1SJohn Floren 		break;
158*cc8875d1SJohn Floren 	}
159*cc8875d1SJohn Floren 
160*cc8875d1SJohn Floren }
161