VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/BIOS/vbe.c@ 66058

Last change on this file since 66058 was 63595, checked in by vboxsync, 8 years ago

revert r110292 as it causes triple faults with certain guests

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1// ============================================================================================
2//
3// Copyright (C) 2002 Jeroen Janssen
4//
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; either
8// version 2 of the License, or (at your option) any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18//
19// ============================================================================================
20//
21// This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card.
22// You can NOT drive any physical vga card with it.
23//
24// ============================================================================================
25//
26// This VBE Bios is based on information taken from :
27// - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org
28//
29// ============================================================================================
30
31
32/*
33 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
34 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
35 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
36 * a choice of LGPL license versions is made available with the language indicating
37 * that LGPLv2 or any later version may be used, or where a choice of which version
38 * of the LGPL is applied is otherwise unspecified.
39 */
40
41// Use VBE new dynamic mode list. Note that without this option, no
42// checks are currently done to make sure that modes fit into the
43// framebuffer!
44#define VBE_NEW_DYN_LIST
45
46#include <inttypes.h>
47#include <stddef.h>
48#include "vbe.h"
49#include "vgadefs.h"
50#include "inlines.h"
51
52// disable VESA/VBE2 check in vbe info
53//#define VBE2_NO_VESA_CHECK
54
55// use bytewise i/o (Longhorn beta issue, not in released Vista)
56#define VBE_BYTEWISE_IO
57
58#ifdef VBE_BYTEWISE_IO
59 extern void do_out_dx_ax();
60 #pragma aux do_out_dx_ax "*";
61 extern void out_w(uint16_t port, uint16_t value);
62 #pragma aux out_w = \
63 "call do_out_dx_ax" \
64 parm [dx] [ax] modify nomemory;
65 extern void do_in_ax_dx();
66 #pragma aux do_in_ax_dx "*";
67 extern uint16_t in_w(uint16_t port);
68 #pragma aux in_w = \
69 "call do_in_ax_dx" \
70 parm [dx] value [ax] modify nomemory;
71#else
72 #define out_w outw
73 #define in_w inw
74#endif
75
76
77/* VESA signatures as integer constants. */
78#define SIG_VBE2 0x32454256 /* 'VBE2' */
79#define SIG_VESA 0x41534556 /* 'VESA' */
80
81
82/* Implemented in assembler. */
83extern void __cdecl vga_compat_setup(void);
84extern void dispi_set_enable(uint16_t enable);
85extern void dispi_set_bank(uint16_t bank);
86extern uint16_t __cdecl dispi_get_max_bpp(void);
87extern void __cdecl dispi_set_bank_farcall(void);
88
89// The current OEM Software Revision of this VBE Bios
90#define VBE_OEM_SOFTWARE_REV 0x0003
91
92// FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
93char vbebios_copyright[] = "VirtualBox VESA BIOS";
94char vbebios_vendor_name[] = VBOX_VENDOR;
95char vbebios_product_name[] = VBOX_PRODUCT " VBE Adapter";
96char vbebios_product_revision[] = VBOX_PRODUCT " Version " VBOX_VERSION_STRING;
97
98char vbebios_info_string[] = "VirtualBox VBE Display Adapter enabled\r\n\r\n";
99char no_vbebios_info_string[] = "No VirtualBox VBE support available!\r\n\r\n";
100
101#ifdef VGA_DEBUG
102char msg_vbe_init[] = "VirtualBox Version " VBOX_VERSION_STRING " VBE Display Adapter\r\n";
103#endif
104
105static void dispi_set_xres(uint16_t xres)
106{
107#ifdef VGA_DEBUG
108 printf("vbe_set_xres: %04x\n", xres);
109#endif
110 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
111 out_w(VBE_DISPI_IOPORT_DATA, xres);
112}
113
114static void dispi_set_yres(uint16_t yres)
115{
116#ifdef VGA_DEBUG
117 printf("vbe_set_yres: %04x\n", yres);
118#endif
119 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
120 out_w(VBE_DISPI_IOPORT_DATA, yres);
121}
122
123static void dispi_set_bpp(uint16_t bpp)
124{
125#ifdef VGA_DEBUG
126 printf("vbe_set_bpp: %02x\n", bpp);
127#endif
128 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
129 out_w(VBE_DISPI_IOPORT_DATA, bpp);
130}
131
132uint16_t in_word(uint16_t port, uint16_t addr)
133{
134 outw(port, addr);
135 return inw(port);
136}
137
138#ifdef VBE_NEW_DYN_LIST
139uint8_t in_byte(uint16_t port, uint16_t addr)
140{
141 outw(port, addr);
142 return inb(port);
143}
144#endif
145
146/* Display "chip" identification helpers. */
147static uint16_t dispi_get_id(void)
148{
149 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
150 return inw(VBE_DISPI_IOPORT_DATA);
151}
152
153static void dispi_set_id(uint16_t chip_id)
154{
155 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
156 outw(VBE_DISPI_IOPORT_DATA, chip_id);
157}
158
159/* VBE Init - Initialise the VESA BIOS Extension (VBE) support
160 * This function does a sanity check on the host side display code interface.
161 */
162void vbe_init(void)
163{
164 dispi_set_id(VBE_DISPI_ID0);
165 if (dispi_get_id() == VBE_DISPI_ID0) {
166 /* VBE support was detected. */
167 write_byte(BIOSMEM_SEG, BIOSMEM_VBE_FLAG, 1);
168 dispi_set_id(VBE_DISPI_ID4);
169 }
170#ifdef DEBUG_VGA
171 printf(msg_vbe_init);
172#endif
173}
174
175/* Find the offset of the desired mode, given its number. */
176#ifdef VBE_NEW_DYN_LIST
177static uint16_t mode_info_find_mode(uint16_t mode, Boolean using_lfb)
178{
179 uint16_t sig, vmode, attrs;
180 uint16_t cur_info_ofs; /* Current offset in mode list. */
181
182 /* Read and check the VBE Extra Data signature. */
183 sig = in_word(VBE_EXTRA_PORT, 0);
184 if (sig != VBEHEADER_MAGIC) {
185#ifdef DEBUG_VGA
186 printf("Signature NOT found! %x\n", sig);
187#endif
188 return 0;
189 }
190
191 cur_info_ofs = sizeof(VBEHeader);
192
193 vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/);
194 while (vmode != VBE_VESA_MODE_END_OF_LIST)
195 {
196 attrs = in_word(VBE_EXTRA_PORT, /*&cur_info->info.ModeAttributes*/cur_info_ofs + offsetof(ModeInfoListItem, info.ModeAttributes) );
197
198 if (vmode == mode)
199 {
200 if (!using_lfb)
201 return cur_info_ofs;
202 else if (attrs & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
203 return cur_info_ofs;
204 else {
205 cur_info_ofs += sizeof(ModeInfoListItem);
206 vmode = in_word(VBE_EXTRA_PORT, /*&cur_info->mode*/cur_info_ofs + offsetof(ModeInfoListItem, mode));
207 }
208 } else {
209 cur_info_ofs += sizeof(ModeInfoListItem);
210 vmode = in_word(VBE_EXTRA_PORT, /*&cur_info->mode*/cur_info_ofs + offsetof(ModeInfoListItem, mode));
211 }
212 }
213 return 0;
214}
215#else
216static ModeInfoListItem* mode_info_find_mode(uint16_t mode, Boolean using_lfb)
217{
218 ModeInfoListItem *cur_info = &mode_info_list;
219
220 while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
221 {
222 if (cur_info->mode == mode)
223 {
224 if (!using_lfb)
225 return cur_info;
226 else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
227 return cur_info;
228 else
229 cur_info++;
230 } else
231 cur_info++;
232 }
233 return 0;
234}
235#endif
236
237#ifndef VBOX
238; VBE Display Info - Display information on screen about the VBE
239
240vbe_display_info:
241 call _vbe_has_vbe_display
242 test ax, ax
243 jz no_vbe_flag
244 mov ax, #0xc000
245 mov ds, ax
246 mov si, #_vbebios_info_string
247 jmp _display_string
248no_vbe_flag:
249 mov ax, #0xc000
250 mov ds, ax
251 mov si, #_no_vbebios_info_string
252 jmp _display_string
253#endif
254
255/** Function 00h - Return VBE Controller Information
256 *
257 * Input:
258 * AX = 4F00h
259 * ES:DI = Pointer to buffer in which to place VbeInfoBlock structure
260 * (VbeSignature should be VBE2 when VBE 2.0 information is desired and
261 * the info block is 512 bytes in size)
262 * Output:
263 * AX = VBE Return Status
264 *
265 */
266void vbe_biosfn_return_controller_information(uint16_t STACK_BASED *AX, uint16_t ES, uint16_t DI)
267{
268 uint16_t status;
269 uint16_t vbe2_info;
270 uint16_t cur_mode = 0;
271 uint16_t cur_ptr=34;
272#ifdef VBE_NEW_DYN_LIST
273 uint16_t cur_info_ofs;
274 uint16_t sig, vmode;
275#else
276 ModeInfoListItem *cur_info = &mode_info_list;
277#endif
278 uint16_t max_bpp = dispi_get_max_bpp();
279 VbeInfoBlock __far *info_block;
280
281 info_block = ES :> (VbeInfoBlock *)DI;
282
283#ifdef VBE_NEW_DYN_LIST
284 /* Read VBE Extra Data signature */
285 sig = in_word(VBE_EXTRA_PORT, 0);
286 if (sig != VBEHEADER_MAGIC)
287 {
288 *AX = 0x0100;
289#ifdef DEBUG_VGA
290 printf("Signature NOT found\n");
291#endif
292 return;
293 }
294 cur_info_ofs = sizeof(VBEHeader);
295#endif
296 status = *AX;
297
298#ifdef VGA_DEBUG
299 printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
300#endif
301
302 vbe2_info = 0;
303
304 /* Don't use a local copy of VbeInfoBlock on the stack; it's too big.
305 * The Ubuntu 8.04 64 bits splash screen emulator can't handle this.
306 */
307#ifdef VBE2_NO_VESA_CHECK
308#else /* !VBE2_NO_VESA_CHECK */
309 // check for VBE2 signature
310 if (info_block->VbeSignature.Sig32 == SIG_VBE2 || info_block->VbeSignature.Sig32 == SIG_VESA)
311 {
312 vbe2_info = 1;
313#ifdef VGA_DEBUG
314 printf("VBE correct VESA/VBE2 signature found\n");
315#endif
316 }
317#endif /* !VBE2_NO_VESA_CHECK */
318
319 /* VBE Signature - the compiler will optimize this into something sane. */
320 info_block->VbeSignature.SigChr[0] = 'V';
321 info_block->VbeSignature.SigChr[1] = 'E';
322 info_block->VbeSignature.SigChr[2] = 'S';
323 info_block->VbeSignature.SigChr[3] = 'A';
324
325 /* VBE Version supported. */
326 info_block->VbeVersion = 0x0200; /* Version 2.0. */
327
328 /* OEM String. */
329 info_block->OemString.Ptr = &vbebios_copyright;
330
331 /* Capabilities if this implementation. */
332 info_block->Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
333 info_block->Capabilities[1] = 0;
334 info_block->Capabilities[2] = 0;
335 info_block->Capabilities[3] = 0;
336
337 /* Video mode list pointer (dynamically generated). */
338 info_block->VideoModePtr_Seg = ES;
339 info_block->VideoModePtr_Off = DI + 34;
340
341 /* Total controller memory in 64K units. */
342 info_block->TotalMemory = in_word(VBE_EXTRA_PORT, 0xffff);
343
344 if (vbe2_info)
345 {
346 /* OEM information. */
347 info_block->OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
348 info_block->OemVendorName.Ptr = &vbebios_vendor_name;
349 info_block->OemProductName.Ptr = &vbebios_product_name;
350 info_block->OemProductRev.Ptr = &vbebios_product_revision;
351 }
352
353#ifdef VBE_NEW_DYN_LIST
354 do
355 {
356 uint8_t data_b;
357
358 data_b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/);
359 if (data_b <= max_bpp)
360 {
361 vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/);
362#ifdef VGA_DEBUG
363 printf("VBE found mode %x => %x\n", vmode, cur_mode);
364#endif
365 write_word(ES, DI + cur_ptr, vmode);
366 cur_mode++;
367 cur_ptr+=2;
368 }
369 cur_info_ofs += sizeof(ModeInfoListItem);
370 vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/);
371 } while (vmode != VBE_VESA_MODE_END_OF_LIST);
372
373 // Add vesa mode list terminator
374 write_word(ES, DI + cur_ptr, vmode);
375#else
376 do
377 {
378 if (cur_info->info.BitsPerPixel <= max_bpp) {
379#ifdef VGA_DEBUG
380 printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
381#endif
382 write_word(ES, DI + cur_ptr, cur_info->mode);
383 cur_mode++;
384 cur_ptr += 2;
385 }
386 cur_info++;
387 } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
388
389 // Add vesa mode list terminator
390 write_word(ES, DI + cur_ptr, cur_info->mode);
391#endif // VBE_NEW_DYN_LIST
392 *AX = 0x004F;
393}
394
395/** Function 01h - Return VBE Mode Information
396 *
397 * Input:
398 * AX = 4F01h
399 * CX = Mode Number
400 * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure
401 * Output:
402 * AX = VBE Return Status
403 *
404 */
405void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI)
406{
407 uint16_t result = 0x0100;
408#ifdef VBE_NEW_DYN_LIST
409 uint16_t cur_info_ofs;
410#else
411 ModeInfoListItem *cur_info;
412#endif
413 Boolean using_lfb;
414 uint8_t win_attr;
415
416#ifdef VGA_DEBUG
417 printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
418#endif
419
420 using_lfb = ((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
421 CX = (CX & 0x1ff);
422
423#ifdef VBE_NEW_DYN_LIST
424 cur_info_ofs = mode_info_find_mode(CX, using_lfb);
425
426 if (cur_info_ofs) {
427 uint16_t i;
428#else
429 cur_info = mode_info_find_mode(CX, using_lfb);
430
431 if (cur_info != 0) {
432#endif
433#ifdef VGA_DEBUG
434 printf("VBE found mode %x\n",CX);
435#endif
436 memsetb(ES, DI, 0, 256); // The mode info size is fixed
437#ifdef VBE_NEW_DYN_LIST
438 for (i = 0; i < sizeof(ModeInfoBlockCompact); i++) {
439 uint8_t b;
440
441 b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info) + i/*(char *)(&(cur_info->info)) + i*/);
442 write_byte(ES, DI + i, b);
443 }
444#else
445 memcpyb(ES, DI, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
446#endif
447 win_attr = read_byte(ES, DI + offsetof(ModeInfoBlock, WinAAttributes));
448 if (win_attr & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
449 write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr), (uint16_t)(dispi_set_bank_farcall));
450 // If BIOS not at 0xC000 -> boom
451 write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr) + 2, 0xC000);
452 }
453 // Update the LFB physical address which may change at runtime
454 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI);
455 write_word(ES, DI + offsetof(ModeInfoBlock, PhysBasePtr) + 2, in_w(VBE_DISPI_IOPORT_DATA));
456
457 result = 0x4f;
458 } else {
459#ifdef VGA_DEBUG
460 printf("VBE *NOT* found mode %x\n",CX);
461#endif
462 result = 0x100;
463 }
464
465 *AX = result;
466}
467
468/** Function 02h - Set VBE Mode
469 *
470 * Input:
471 * AX = 4F02h
472 * BX = Desired Mode to set
473 * ES:DI = Pointer to CRTCInfoBlock structure
474 * Output:
475 * AX = VBE Return Status
476 *
477 */
478void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI)
479{
480 uint16_t result;
481#ifdef VBE_NEW_DYN_LIST
482 uint16_t cur_info_ofs;
483#else
484 ModeInfoListItem *cur_info;
485#endif
486 Boolean using_lfb;
487 uint8_t no_clear;
488 uint8_t lfb_flag;
489
490 using_lfb = ((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
491 lfb_flag = using_lfb ? VBE_DISPI_LFB_ENABLED : 0;
492 no_clear = ((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY) ? VBE_DISPI_NOCLEARMEM : 0;
493
494 BX = (BX & 0x1ff);
495
496 // check for non vesa mode
497 if (BX < VBE_MODE_VESA_DEFINED)
498 {
499 uint8_t mode;
500
501 dispi_set_enable(VBE_DISPI_DISABLED);
502 // call the vgabios in order to set the video mode
503 // this allows for going back to textmode with a VBE call (some applications expect that to work)
504 mode = (BX & 0xff);
505 biosfn_set_video_mode(mode);
506 result = 0x4f;
507 goto leave;
508 }
509
510#ifdef VBE_NEW_DYN_LIST
511 cur_info_ofs = mode_info_find_mode(BX, using_lfb);
512
513 if (cur_info_ofs != 0)
514 {
515 uint16_t xres, yres;
516 uint8_t bpp;
517
518 xres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.XResolution) /*&cur_info->info.XResolution*/);
519 yres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.YResolution) /*&cur_info->info.YResolution*/);
520 bpp = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/);
521
522#ifdef VGA_DEBUG
523 printf("VBE found mode %x, setting:\n", BX);
524 printf("\txres%x yres%x bpp%x\n", xres, yres, bpp);
525#endif
526#else
527 cur_info = mode_info_find_mode(BX, using_lfb);
528
529 if (cur_info != 0)
530 {
531#ifdef VGA_DEBUG
532 printf("VBE found mode %x, setting:\n", BX);
533 printf("\txres%x yres%x bpp%x\n",
534 cur_info->info.XResolution,
535 cur_info->info.YResolution,
536 cur_info->info.BitsPerPixel);
537#endif
538#endif // VBE_NEW_DYN_LIST
539
540 // first disable current mode (when switching between vesa modi)
541 dispi_set_enable(VBE_DISPI_DISABLED);
542
543#ifdef VBE_NEW_DYN_LIST
544 if (bpp == 4)
545#else
546 if (cur_info->info.BitsPerPixel == 4)
547#endif
548 {
549 biosfn_set_video_mode(0x6a);
550 }
551
552#ifdef VBE_NEW_DYN_LIST
553 dispi_set_bpp(bpp);
554 dispi_set_xres(xres);
555 dispi_set_yres(yres);
556#else
557 dispi_set_bpp(cur_info->info.BitsPerPixel);
558 dispi_set_xres(cur_info->info.XResolution);
559 dispi_set_yres(cur_info->info.YResolution);
560#endif
561 dispi_set_bank(0);
562 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
563 vga_compat_setup();
564
565 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
566 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
567
568 result = 0x4f;
569 }
570 else
571 {
572#ifdef VGA_DEBUG
573 printf("VBE *NOT* found mode %x\n" , BX);
574#endif
575 result = 0x100;
576 }
577
578leave:
579 *AX = result;
580}
581
582uint16_t vbe_biosfn_read_video_state_size(void)
583{
584 return 9 * 2;
585}
586
587void vbe_biosfn_save_video_state(uint16_t ES, uint16_t BX)
588{
589 uint16_t enable, i;
590
591 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
592 enable = inw(VBE_DISPI_IOPORT_DATA);
593 write_word(ES, BX, enable);
594 BX += 2;
595 if (!(enable & VBE_DISPI_ENABLED))
596 return;
597 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
598 if (i != VBE_DISPI_INDEX_ENABLE) {
599 outw(VBE_DISPI_IOPORT_INDEX, i);
600 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
601 BX += 2;
602 }
603 }
604}
605
606
607void vbe_biosfn_restore_video_state(uint16_t ES, uint16_t BX)
608{
609 uint16_t enable, i;
610
611 enable = read_word(ES, BX);
612 BX += 2;
613
614 if (!(enable & VBE_DISPI_ENABLED)) {
615 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
616 outw(VBE_DISPI_IOPORT_DATA, enable);
617 } else {
618 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
619 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
620 BX += 2;
621 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
622 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
623 BX += 2;
624 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
625 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
626 BX += 2;
627 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
628 outw(VBE_DISPI_IOPORT_DATA, enable);
629
630 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
631 outw(VBE_DISPI_IOPORT_INDEX, i);
632 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
633 BX += 2;
634 }
635 }
636}
637
638/** Function 04h - Save/Restore State
639 *
640 * Input:
641 * AX = 4F04h
642 * DL = 00h Return Save/Restore State buffer size
643 * 01h Save State
644 * 02h Restore State
645 * CX = Requested states
646 * ES:BX = Pointer to buffer (if DL <> 00h)
647 * Output:
648 * AX = VBE Return Status
649 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
650 *
651 */
652void vbe_biosfn_save_restore_state(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t DX,
653 uint16_t ES, uint16_t STACK_BASED *BX)
654{
655 uint16_t result, val;
656
657 result = 0x004F;
658 switch(GET_DL()) {
659 case 0x00:
660 val = biosfn_read_video_state_size2(CX);
661#ifdef VGA_DEBUG
662 printf("VGA state size=%x\n", val);
663#endif
664 if (CX & 8)
665 val += vbe_biosfn_read_video_state_size();
666 *BX = (val + 63) / 64;
667 break;
668 case 0x01:
669 val = *BX;
670 val = biosfn_save_video_state(CX, ES, val);
671#ifdef VGA_DEBUG
672 printf("VGA save_state offset=%x\n", val);
673#endif
674 if (CX & 8)
675 vbe_biosfn_save_video_state(ES, val);
676 break;
677 case 0x02:
678 val = *BX;
679 val = biosfn_restore_video_state(CX, ES, val);
680#ifdef VGA_DEBUG
681 printf("VGA restore_state offset=%x\n", val);
682#endif
683 if (CX & 8)
684 vbe_biosfn_restore_video_state(ES, val);
685 break;
686 default:
687 // function failed
688 result = 0x100;
689 break;
690 }
691 *AX = result;
692}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette