1 // Video Bios Extensions handlers
3 // Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2011 Julian Pidancet <julian.pidancet@citrix.com>
5 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
7 // This file may be distributed under the terms of the GNU LGPLv3 license.
9 #include "biosvar.h" // GET_GLOBAL
10 #include "bregs.h" // struct bregs
11 #include "config.h" // CONFIG_*
12 #include "output.h" // dprintf
13 #include "std/vbe.h" // struct vbe_info
14 #include "string.h" // memset_far
15 #include "vgabios.h" // handle_104f
16 #include "vgahw.h" // vgahw_set_mode
18 u32 VBE_total_memory VAR16 = 256 * 1024;
19 u32 VBE_capabilities VAR16;
20 u32 VBE_framebuffer VAR16;
21 u16 VBE_win_granularity VAR16;
24 vbe_104f00(struct bregs *regs)
27 struct vbe_info *info = (void*)(regs->di+0);
29 if (GET_FARVAR(seg, info->signature) == VBE2_SIGNATURE) {
30 dprintf(4, "Get VBE Controller: VBE2 Signature found\n");
31 } else if (GET_FARVAR(seg, info->signature) == VESA_SIGNATURE) {
32 dprintf(4, "Get VBE Controller: VESA Signature found\n");
34 dprintf(4, "Get VBE Controller: Invalid Signature\n");
37 memset_far(seg, info, 0, sizeof(*info));
39 SET_FARVAR(seg, info->signature, VESA_SIGNATURE);
41 SET_FARVAR(seg, info->version, 0x0300);
43 SET_FARVAR(seg, info->oem_string,
44 SEGOFF(get_global_seg(), (u32)VBE_OEM_STRING));
45 SET_FARVAR(seg, info->capabilities, GET_GLOBAL(VBE_capabilities));
47 /* We generate our mode list in the reserved field of the info block */
48 u16 *destmode = (void*)info->reserved;
49 SET_FARVAR(seg, info->video_mode, SEGOFF(seg, (u32)destmode));
51 /* Total memory (in 64k blocks) */
52 SET_FARVAR(seg, info->total_memory
53 , GET_GLOBAL(VBE_total_memory) / (64*1024));
55 SET_FARVAR(seg, info->oem_vendor_string,
56 SEGOFF(get_global_seg(), (u32)VBE_VENDOR_STRING));
57 SET_FARVAR(seg, info->oem_product_string,
58 SEGOFF(get_global_seg(), (u32)VBE_PRODUCT_STRING));
59 SET_FARVAR(seg, info->oem_revision_string,
60 SEGOFF(get_global_seg(), (u32)VBE_REVISION_STRING));
62 /* Fill list of modes */
63 u16 *last = (void*)&info->reserved[sizeof(info->reserved)];
64 vgahw_list_modes(seg, destmode, last - 1);
70 vbe_104f01(struct bregs *regs)
73 struct vbe_mode_info *info = (void*)(regs->di+0);
76 dprintf(1, "VBE mode info request: %x\n", mode);
78 struct vgamode_s *vmode_g = vgahw_find_mode(mode & ~MF_VBEFLAGS);
80 dprintf(1, "VBE mode %x not found\n", mode);
85 memset_far(seg, info, 0, sizeof(*info));
87 // Basic information about video controller.
88 u32 win_granularity = GET_GLOBAL(VBE_win_granularity);
89 SET_FARVAR(seg, info->winA_attributes,
90 (win_granularity ? VBE_WINDOW_ATTRIBUTE_RELOCATABLE : 0) |
91 VBE_WINDOW_ATTRIBUTE_READABLE |
92 VBE_WINDOW_ATTRIBUTE_WRITEABLE);
93 SET_FARVAR(seg, info->winB_attributes, 0);
94 SET_FARVAR(seg, info->win_granularity, win_granularity);
95 SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */
96 SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart));
97 SET_FARVAR(seg, info->winB_seg, 0x0);
98 extern void entry_104f05(void);
99 SET_FARVAR(seg, info->win_func_ptr
100 , SEGOFF(get_global_seg(), (u32)entry_104f05));
101 // Basic information about mode.
102 int width = GET_GLOBAL(vmode_g->width);
103 int height = GET_GLOBAL(vmode_g->height);
104 int linesize = DIV_ROUND_UP(width * vga_bpp(vmode_g), 8);
105 SET_FARVAR(seg, info->bytes_per_scanline, linesize);
106 SET_FARVAR(seg, info->xres, width);
107 SET_FARVAR(seg, info->yres, height);
108 SET_FARVAR(seg, info->xcharsize, GET_GLOBAL(vmode_g->cwidth));
109 SET_FARVAR(seg, info->ycharsize, GET_GLOBAL(vmode_g->cheight));
110 int depth = GET_GLOBAL(vmode_g->depth);
111 SET_FARVAR(seg, info->bits_per_pixel, depth);
112 u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
113 SET_FARVAR(seg, info->mem_model, memmodel);
114 SET_FARVAR(seg, info->reserved0, 1);
116 // Mode specific info.
117 u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED |
118 VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE |
119 VBE_MODE_ATTRIBUTE_COLOR_MODE |
120 VBE_MODE_ATTRIBUTE_GRAPHICS_MODE |
121 VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE;
123 int planes = 1, banks = 1;
124 u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024);
127 mode_attr &= ~VBE_MODE_ATTRIBUTE_GRAPHICS_MODE;
128 mode_attr |= VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT;
129 if (GET_GLOBAL(vmode_g->sstart) == SEG_MTEXT)
130 mode_attr &= ~VBE_MODE_ATTRIBUTE_COLOR_MODE;
136 SET_FARVAR(seg, info->bank_size, 8);
143 framebuffer = GET_GLOBAL(VBE_framebuffer);
145 mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE;
152 SET_FARVAR(seg, info->mode_attributes, mode_attr);
153 SET_FARVAR(seg, info->planes, planes);
154 SET_FARVAR(seg, info->pages, pages - 1);
155 SET_FARVAR(seg, info->banks, banks);
157 // Pixel color breakdown
158 u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos;
160 case 15: r_size = 5; r_pos = 10; g_size = 5; g_pos = 5;
161 b_size = 5; b_pos = 0; a_size = 1; a_pos = 15; break;
162 case 16: r_size = 5; r_pos = 11; g_size = 6; g_pos = 5;
163 b_size = 5; b_pos = 0; a_size = 0; a_pos = 0; break;
164 case 24: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8;
165 b_size = 8; b_pos = 0; a_size = 0; a_pos = 0; break;
166 case 32: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8;
167 b_size = 8; b_pos = 0; a_size = 8; a_pos = 24;
168 SET_FARVAR(seg, info->directcolor_info,
169 VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE);
171 default: r_size = 0; r_pos = 0; g_size = 0; g_pos = 0;
172 b_size = 0; b_pos = 0; a_size = 0; a_pos = 0; break;
174 SET_FARVAR(seg, info->red_size, r_size);
175 SET_FARVAR(seg, info->red_pos, r_pos);
176 SET_FARVAR(seg, info->green_size, g_size);
177 SET_FARVAR(seg, info->green_pos, g_pos);
178 SET_FARVAR(seg, info->blue_size, b_size);
179 SET_FARVAR(seg, info->blue_pos, b_pos);
180 SET_FARVAR(seg, info->alpha_size, a_size);
181 SET_FARVAR(seg, info->alpha_pos, a_pos);
183 // Linear framebuffer info.
185 SET_FARVAR(seg, info->phys_base, framebuffer);
187 SET_FARVAR(seg, info->reserved1, 0);
188 SET_FARVAR(seg, info->reserved2, 0);
189 SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize);
190 SET_FARVAR(seg, info->linear_pages, 0);
191 SET_FARVAR(seg, info->linear_red_size, r_size);
192 SET_FARVAR(seg, info->linear_red_pos, r_pos);
193 SET_FARVAR(seg, info->linear_green_size, g_size);
194 SET_FARVAR(seg, info->linear_green_pos, g_pos);
195 SET_FARVAR(seg, info->linear_blue_size, b_size);
196 SET_FARVAR(seg, info->linear_blue_pos, b_pos);
197 SET_FARVAR(seg, info->linear_alpha_size, a_size);
198 SET_FARVAR(seg, info->linear_alpha_pos, a_pos);
205 vbe_104f02(struct bregs *regs)
207 dprintf(1, "VBE mode set: %x\n", regs->bx);
209 int mode = regs->bx & ~MF_VBEFLAGS;
210 int flags = regs->bx & MF_VBEFLAGS;
211 int ret = vga_set_mode(mode, flags);
218 vbe_104f03(struct bregs *regs)
220 regs->bx = GET_BDA_EXT(vbe_mode);
221 dprintf(1, "VBE current mode=%x\n", regs->bx);
226 vbe_104f04(struct bregs *regs)
229 void *data = (void*)(regs->bx+0);
230 u16 states = regs->cx;
232 if (states & ~0x0f || cmd > 2)
234 int ret = vgahw_save_restore(states | (cmd<<8), seg, data);
246 vbe_104f05(struct bregs *regs)
248 if (regs->bh > 1 || regs->bl > 1)
250 if (GET_BDA_EXT(vbe_mode) & MF_LINEARFB) {
251 regs->ah = VBE_RETURN_STATUS_INVALID;
254 struct vgamode_s *vmode_g = get_current_mode();
258 int ret = vgahw_get_window(vmode_g, regs->bl);
265 int ret = vgahw_set_window(vmode_g, regs->bl, regs->dx);
275 vbe_104f06(struct bregs *regs)
279 struct vgamode_s *vmode_g = get_current_mode();
282 int bpp = vga_bpp(vmode_g);
284 if (regs->bl == 0x00) {
285 int ret = vgahw_set_linelength(vmode_g, DIV_ROUND_UP(regs->cx * bpp, 8));
288 } else if (regs->bl == 0x02) {
289 int ret = vgahw_set_linelength(vmode_g, regs->cx);
293 int linelength = vgahw_get_linelength(vmode_g);
297 regs->bx = linelength;
298 regs->cx = (linelength * 8) / bpp;
299 regs->dx = GET_GLOBAL(VBE_total_memory) / linelength;
307 vbe_104f07(struct bregs *regs)
309 struct vgamode_s *vmode_g = get_current_mode();
312 int bpp = vga_bpp(vmode_g);
313 int linelength = vgahw_get_linelength(vmode_g);
321 ret = vgahw_set_displaystart(
322 vmode_g, DIV_ROUND_UP(regs->cx * bpp, 8) + linelength * regs->dx);
327 ret = vgahw_get_displaystart(vmode_g);
330 regs->dx = ret / linelength;
331 regs->cx = (ret % linelength) * 8 / bpp;
343 vbe_104f08(struct bregs *regs)
345 struct vgamode_s *vmode_g = get_current_mode();
348 u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
349 if (memmodel == MM_DIRECT || memmodel == MM_YUV) {
356 int ret = vgahw_set_dacformat(vmode_g, regs->bh);
360 int ret = vgahw_get_dacformat(vmode_g);
371 vbe_104f0a(struct bregs *regs)
378 vbe_104f10(struct bregs *regs)
385 MASK_BDA_EXT(flags, BF_PM_MASK, regs->bh & BF_PM_MASK);
388 regs->bh = GET_BDA_EXT(flags) & BF_PM_MASK;
398 vbe_104fXX(struct bregs *regs)
405 handle_104f(struct bregs *regs)
407 if (!CONFIG_VGA_VBE) {
413 case 0x00: vbe_104f00(regs); break;
414 case 0x01: vbe_104f01(regs); break;
415 case 0x02: vbe_104f02(regs); break;
416 case 0x03: vbe_104f03(regs); break;
417 case 0x04: vbe_104f04(regs); break;
418 case 0x05: vbe_104f05(regs); break;
419 case 0x06: vbe_104f06(regs); break;
420 case 0x07: vbe_104f07(regs); break;
421 case 0x08: vbe_104f08(regs); break;
422 case 0x0a: vbe_104f0a(regs); break;
423 case 0x10: vbe_104f10(regs); break;
424 default: vbe_104fXX(regs); break;